Overview
Exploration of all the data collected on the presence points + randomly generated background points
A note to anyone who might happen to stumble across this… I am a beginner in R and have had no exposure to similar languages. I don’t know what I’m doing. The code herein is unlikely to be elegant and there are probably more efficient ways of running the code.
Built with ‘r getRversion()’.
Package dependencies
You can load them using the following code which uses a function called ipak. Note this function checks to see if the packages are installed first. The “include=FALSE” supresses the package installation text appearing in the document…
presence points
Read in the presence points
presence <- read.csv("../output/bio/presence_points_without_envdata_relooped_glbathy.csv", header = TRUE)
head(presence)
Update: Who sampled in which year and which month:
year
inst_by_yr <- with(presence, table(year, institutioncode))
write.csv(inst_by_yr, file = "../output/bio/institutioncode_by_yr.csv")
inst_by_yr
institutioncode
year ARC DFOCENARC DFOGulf DFOISDM DFOMTMS DFONL DFOQC MaineDMR NEFSC ROM
1998 1 0 48 1 21 582 3 0 1 0
1999 0 0 89 1 74 503 0 0 0 0
2000 10 0 98 7 58 532 0 0 0 0
2001 0 0 50 1 44 546 0 0 0 0
2002 7 0 103 1 52 493 0 0 0 0
2003 0 0 42 3 42 573 0 0 0 0
2004 0 0 90 2 24 668 177 0 0 0
2005 1 14 108 0 83 472 216 7 0 0
2006 4 11 78 4 80 480 234 6 0 0
2007 1 42 85 1 37 467 233 0 0 2
2008 0 10 81 5 38 477 263 0 0 0
2009 0 10 78 0 30 511 125 3 0 0
2010 1 10 94 0 44 529 109 0 0 0
2011 0 22 77 0 13 479 139 0 0 0
2012 0 8 85 0 10 0 148 0 0 0
2013 2 18 68 0 21 0 127 0 0 0
2014 1 22 101 0 6 0 0 0 0 0
2015 3 12 0 0 0 0 0 0 0 0
month
inst_by_mt <- with(presence, table(month, institutioncode))
write.csv(inst_by_mt, file = "../output/bio/institutioncode_by_mth.csv")
inst_by_mt
institutioncode
month ARC DFOCENARC DFOGulf DFOISDM DFOMTMS DFONL DFOQC MaineDMR NEFSC ROM
1 0 0 0 0 0 263 0 0 0 0
2 0 0 0 0 7 4 0 0 0 0
3 1 0 0 3 342 0 0 0 0 0
4 0 0 0 3 11 732 0 0 1 0
5 1 0 0 0 0 1106 17 8 0 0
6 1 0 0 0 0 1694 24 3 0 0
7 20 19 0 17 304 52 33 0 0 2
8 1 73 7 1 14 0 1735 0 0 0
9 8 23 1380 3 0 6 14 0 0 0
10 0 63 5 3 0 545 2 2 0 0
11 8 1 0 3 0 1811 0 3 0 0
12 0 0 0 1 0 1136 0 0 0 0
environmental correlates
- Get the max, min, an mean values and add into a dataframe
Temperature
temp_depth_max <- max(presence$temp_depth, na.rm = TRUE)
temp_depth_min <- min(presence$temp_depth, na.rm = TRUE)
temp_depth_mean <- mean(presence$temp_depth, na.rm = TRUE)
temp_surface_max <- max(presence$temp_surface, na.rm = TRUE)
temp_surface_min <- min(presence$temp_surface, na.rm = TRUE)
temp_surface_mean <- mean(presence$temp_surface, na.rm = TRUE)
Salinity
sal_depth_max <- max(presence$salinity_depth, na.rm = TRUE)
sal_depth_min <- min(presence$salinity_depth, na.rm = TRUE)
sal_depth_mean <- mean(presence$salinity_depth, na.rm = TRUE)
sal_surface_max <- max(presence$salinity_surface, na.rm = TRUE)
sal_surface_min <- min(presence$salinity_surface, na.rm = TRUE)
sal_surface_mean <- mean(presence$salinity_surface, na.rm = TRUE)
Chl
chl_depth_max <- max(presence$chl_depth, na.rm = TRUE)
chl_depth_min <- min(presence$chl_depth, na.rm = TRUE)
chl_depth_mean <- mean(presence$chl_depth, na.rm = TRUE)
chl_surface_max <- max(presence$chl_surface, na.rm = TRUE)
chl_surface_min <- min(presence$chl_surface, na.rm = TRUE)
chl_surface_mean <- mean(presence$chl_surface, na.rm = TRUE)
O2
o2_depth_max <- max(presence$o2_depth, na.rm = TRUE)
o2_depth_min <- min(presence$o2_depth, na.rm = TRUE)
o2_depth_mean <- mean(presence$o2_depth, na.rm = TRUE)
o2_surface_max <- max(presence$o2_surface, na.rm = TRUE)
o2_surface_min <- min(presence$o2_surface, na.rm = TRUE)
o2_surface_mean <- mean(presence$o2_surface, na.rm = TRUE)
MLP
mlp_surface_max <- max(presence$mlp_surface, na.rm = TRUE)
mlp_surface_min <- min(presence$mlp_surface, na.rm = TRUE)
mlp_surface_mean <- mean(presence$mlp_surface, na.rm = TRUE)
SSH
ssh_surface_max <- max(presence$ssh_surface, na.rm = TRUE)
ssh_surface_min <- min(presence$ssh_surface, na.rm = TRUE)
ssh_surface_mean <- mean(presence$ssh_surface, na.rm = TRUE)
create matrix
td <- c(temp_depth_max, temp_depth_min, temp_depth_mean)
ts <- c(temp_surface_max, temp_surface_min, temp_surface_mean)
sd <- c(sal_depth_max, sal_depth_min, sal_depth_mean)
ss <- c(sal_surface_max, sal_surface_min, sal_surface_mean)
cd <- c(sal_depth_max, sal_depth_min, sal_depth_mean)
cs <- c(sal_surface_max, sal_surface_min, sal_surface_mean)
od <- c(o2_depth_max, o2_depth_min, o2_depth_mean)
os <- c(o2_surface_max, o2_surface_min, o2_surface_mean)
mlp <- c(mlp_surface_max, mlp_surface_min, mlp_surface_mean)
ssh <- c(ssh_surface_max, ssh_surface_min, ssh_surface_mean)
env_stats <- rbind(td, ts, sd, ss, cd, cs, od, os, mlp, ssh)
row.names(env_stats) <- c("Temp Depth", "Temp Surface", "Salinity Depth", "Salinity Surface", "Chl Depth", "Chl Surface", "Oxygen Depth", "Oxygen Surface", "MLP", "SSH")
colnames(env_stats) <- c("Max", "Min", "Mean")
write.csv(env_stats, "../output/env/env_correlates_basic_stats.csv", row.names = TRUE)
env_stats
Max Min Mean
Temp Depth 289.0834045 271.2114868 274.9217164
Temp Surface 293.3608093 271.6101074 280.4476878
Salinity Depth 35.5045395 22.1449070 33.4295117
Salinity Surface 34.3667259 13.5929441 30.2518319
Chl Depth 35.5045395 22.1449070 33.4295117
Chl Surface 34.3667259 13.5929441 30.2518319
Oxygen Depth 377.2959595 0.9998450 279.6701444
Oxygen Surface 385.2262878 238.3178253 315.1620514
MLP 108.2339201 10.6823719 18.1911518
SSH -0.2825949 -0.8503166 -0.5334292
Hmm some potentially suspicious values here in - Oxygen Depth min - mlp Max and maybe also - Salinity Depth min - Salinity Surface min - CHL depth min - CHL depth max
lets just see where these values appear and check the netcdf layers. Note I will check these values in cygwin using the cdo operator infov on the netcdfs (to ensure there was no issue with processing in R).
get the year and month these values appeared in
o2d_check_yr <- subset(presence$year, presence$o2_depth == o2_depth_min)
o2d_check_mth <- subset(presence$month, presence$o2_depth == o2_depth_min)
O2 depth min is in 2005_08
And value seems correct
mlp_check_yr <- subset(presence$year, presence$mlp_surface == mlp_surface_max)
mlp_check_mth <- subset(presence$month, presence$mlp_surface == mlp_surface_max)
mlp max in in 2007_12
And yes the value seems correct
sald_check_yr <- subset(presence$year, presence$salinity_depth == sal_depth_max)
sald_check_mth <- subset(presence$month, presence$salinity_depth == sal_depth_max)
year month 2001_05
also seems correct
sals_check_yr <- subset(presence$year, presence$salinity_surface == sal_surface_min)
sals_check_mth <- subset(presence$month, presence$salinity_surface == sal_surface_min)
year month 21998_06
ok again…
Leave the rest
simple plots of env. correlates
temperature
par(mfrow=c(1,2))
plot(presence$temp_depth, main = "Temp at Depth (Various)", ylab = "Kelvin")
plot(presence$temp_surface, main = "Temp at Surface", ylab = "Kelvin")
dev.copy(png, "../output/env/simple_plots/temperature_simpleplot.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

Hmm not necessarily very helpful. But anyway, lets carry on
salinity
par(mfrow=c(1,2))
plot(presence$salinity_depth, main = "Salinity at Depth (Various)", ylab = "Practical Salinity Units")
plot(presence$salinity_surface, main = "Salinity at Surface", ylab = "Practical Salinity Units")
dev.copy(png,"../output/env/simple_plots/salinity_simpleplot.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

Chlorophyll
par(mfrow=c(1,2))
plot(presence$chl_depth, main = "Chl at Depth (Various)", ylab = "Chl (mmol.m-3)")
plot(presence$chl_surface, main = "Chl at Surface", ylab = "Chl (mmol.m-3)")
dev.copy(png,"../output/env/simple_plots/chl_simpleplot.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

O2
par(mfrow=c(1,2))
plot(presence$o2_depth, main = "Dissolved Oxygen at Depth (Various)", ylab = "Chl (mmol.m-3)")
plot(presence$o2_surface, main = "Dissolved Oxygen at Surface", ylab = "O2 (mmol.m-3)")
dev.copy(png,"../output/env/simple_plots/o2_simpleplot.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

mlp
plot(presence$mlp_surface, main = "Mixed Layer Thickness", ylab = "Depth (m)")
dev.copy(png,"../output/env/simple_plots/mlp_simpleplot.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

SSH
plot(presence$ssh_surface, main = "Sea Surface Height", ylab = "Height (m)")
dev.copy(png,"../output/env/simple_plots/ssh_simpleplot.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

XXX SAM - YOU WANT TO THINK ABOUT DOING THIS BY DEPTH RATHER THAN ALL DEPTHS)
unique_depths <- unique(presence$depthlayerno)
unique_depthdordered <- sort(unique_depths) #just puts the list in oder with no NA
length(unique_depthdordered)
[1] 39
ouch - 39 layers… a job for a boxplot probably
frequency plots of env. corr
temperature
hist(presence$temp_surface, main = "Temp at Surface", xlab = "Kelvin")
dev.copy(png, "../output/env/simple_plots/temperature_surface_histogram.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

hist(presence$temp_dept, main = "Temp at Depth", xlab = "Kelvin")
dev.copy(png, "../output/env/simple_plots/temperature_depth_histogram.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

chl
hist(presence$chl_surface, main = "Chlorophyll at Surface", xlab = "Chlorophyll Concentrations (mmol.m-3)")
dev.copy(png, "../output/env/simple_plots/chl_surface_histogram.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

hist(presence$chl_depth, main = "Chlorophyll at Observation Depth", xlab = "Chlorophyll Concentrations (mmol.m-3)")
dev.copy(png, "../output/env/simple_plots/chl_depth_histogram.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

salinity
hist(presence$salinity_surface, main = "Salinity at Surface", xlab = "Salinity Practical Salinity Unit (PSU)")
dev.copy(png, "../output/env/simple_plots/sal_surface_histogram.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

hist(presence$salinity_depth, main = "Salinity at Observation Depth", xlab = "Salinity Practical Salinity Unit (PSU)")
dev.copy(png, "../output/env/simple_plots/sal_depth_histogram.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

oxygen
hist(presence$o2_surface, main = "Dissolved Oxygen at Surface", xlab = "Mole Concentration of Dissolved Oxygen in Sea Water (mmol.m-3)")
dev.copy(png, "../output/env/simple_plots/o2_surface_histogram.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

hist(presence$o2_depth, main = "Dissolved Oxygen at Observation Depth", xlab = "Mole Concentration of Dissolved Oxygen in Sea Water (mmol.m-3)")
dev.copy(png, "../output/env/simple_plots/o2_depth_histogram.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

MLP
hist(presence$mlp, main = "Mixed Layer Thickness at Observation", xlab = "Mixed Layer Thickness (m)")
dev.copy(png, "../output/env/simple_plots/mlp_surface_histogram.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ssh
hist(presence$ssh, main = "Sea Surface Height at Observation", xlab = "Sea Surface Height (m)")
dev.copy(png, "../output/env/simple_plots/ssh_surface_histogram.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

simple boxplots of env. corr
Same as above but with boxplots (may provide some more useful info)
individual plots of each variable
par(mfrow=c(1,2))
boxplot(presence$chl_depth, main = "Chlorphyll at Depth (Various)", ylab = "mmol.m-3")
boxplot(presence$chl_surface, main = "Chlorphyll at Surface", ylab = "mmol.m-3")
dev.copy(png, "../output/env/simple_plots/chl_boxplot.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(presence$temp_depth ~ presence$month, xlab = "month", ylab = "Temperature (Kelvin)", main = "Temperature at Observation Depth per Month")
dev.copy(png, "../output/env/simple_plots/temperature_boxplot_dept_month.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(presence$chl_depth ~ presence$month, xlab = "month", ylab = "Chlorophyll Concentrations (mmol.m-3)", main = "Chlorophyll at Observation Depth per Month")
dev.copy(png, "../output/env/simple_plots/chlorophyll_boxplot_dept_month.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(presence$salinity_depth ~ presence$month, xlab = "month", ylab = "Salinity Practical Salinity Unit (PSU)", main = "Salinity at Observation Depth per Month")
dev.copy(png, "../output/env/simple_plots/salinity_boxplot_dept_month.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(presence$o2_depth ~ presence$month, xlab = "month", ylab = "Mole Concentration of Dissolved Oxygen in Sea Water (mmol.m-3)", main = "Dissolved Oxygen at Observation Depth per Month")
dev.copy(png, "../output/env/simple_plots/o2_boxplot_dept_month.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(presence$mlp_surface ~ presence$month, xlab = "month", ylab = "Mixed Layer Thickness (m)", main = "Mixed Layer Thickness at Observation per Month")
dev.copy(png, "../output/env/simple_plots/mlp_boxplot_dept_month.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(presence$ssh_surface ~ presence$month, xlab = "month", ylab = "Sea Surface Height (m)", main = "Sea Surface Height at Observation per Month")
dev.copy(png, "../output/env/simple_plots/ssh_boxplot_dept_month.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(presence$temp_depth ~ presence$year, xlab = "Year", ylab = "Temperature (Kelvin)", main = "Temperature at Observation Depth per Year")
dev.copy(png, "../output/env/simple_plots/temperature_boxplot_dept_year.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(presence$chl_depth ~ presence$year, xlab = "Year", ylab = "Chlorophyll Concentrations (mmol.m-3)", main = "Chlorophyll at Observation Depth per Year")
dev.copy(png, "../output/env/simple_plots/chl_boxplot_dept_year.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(presence$salinity_depth ~ presence$year, xlab = "Year", ylab = "Salinity Practical Salinity Unit (PSU)", main = "Salinity at Observation Depth per Year")
dev.copy(png, "../output/env/simple_plots/salinity_boxplot_dept_year.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(presence$o2_depth ~ presence$year, xlab = "Year", ylab = "Mole Concentration of Dissolved Oxygen in Sea Water (mmol.m-3)", main = "Dissolved Oxygen at Observation Depth per Year")
dev.copy(png, "../output/env/simple_plots/oxygen_boxplot_dept_year.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(presence$mlp ~ presence$year, xlab = "Year", ylab = "Mixed Layer Thickness (m)", main = "Mixed Layer Thickness at Observation per Year")
dev.copy(png, "../output/env/simple_plots/mlp_boxplot_dept_year.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(presence$ssh ~ presence$year, xlab = "Year", ylab = "Sea Surface Height (m)", main = "Sea Surface Height at Observation per Year")
dev.copy(png, "../output/env/simple_plots/ssh_boxplot_dept_year.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(presence$temp_surface ~ presence$month, xlab = "month", ylab = "Temperature (Kelvin)", main = "Temperature at Observation (Surface) per Month")
dev.copy(png, "../output/env/simple_plots/temperature_boxplot_surface_month.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(presence$chl_surface ~ presence$month, xlab = "month", ylab = "Chlorophyll Concentrations (mmol.m-3)", main = "Chlorophyll at Observation (Surface) per Month")
dev.copy(png, "../output/env/simple_plots/chlorophyll_boxplot_surface_month.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(presence$salinity_surface ~ presence$month, xlab = "month", ylab = "Salinity Practical Salinity Unit (PSU)", main = "Salinity at Observation (Surface) per Month")
dev.copy(png, "../output/env/simple_plots/salinity_boxplot_surface_month.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(presence$o2_surface ~ presence$month, xlab = "month", ylab = "Mole Concentration of Dissolved Oxygen in Sea Water (mmol.m-3)", main = "Dissolved Oxygen at Observation (Surface) per Month")
dev.copy(png, "../output/env/simple_plots/o2_boxplot_surface_month.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(presence$mlp_surface ~ presence$month, xlab = "month", ylab = "Mixed Layer Thickness (m)", main = "Mixed Layer Thickness at Observation per Month")
dev.copy(png, "../output/env/simple_plots/mlp_boxplot_surface_month.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(presence$ssh_surface ~ presence$month, xlab = "month", ylab = "Sea Surface Height (m)", main = "Sea Surface Height at Observation per Month")
dev.copy(png, "../output/env/simple_plots/ssh_boxplot_surface_month.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(presence$temp_surface ~ presence$year, xlab = "Year", ylab = "Temperature (Kelvin)", main = "Temperature at Observation (Surface) per Year")
dev.copy(png, "../output/env/simple_plots/temperature_boxplot_surface_year.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(presence$chl_surface ~ presence$year, xlab = "Year", ylab = "Chlorophyll Concentrations (mmol.m-3)", main = "Chlorophyll at Observation (Surface) per Year")
dev.copy(png, "../output/env/simple_plots/chl_boxplot_surface_year.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(presence$salinity_surface ~ presence$year, xlab = "Year", ylab = "Salinity Practical Salinity Unit (PSU)", main = "Salinity at Observation (Surface) per Year")
dev.copy(png, "../output/env/simple_plots/salinity_boxplot_surface_year.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(presence$o2_surface ~ presence$year, xlab = "Year", ylab = "Mole Concentration of Dissolved Oxygen in Sea Water (mmol.m-3)", main = "Dissolved Oxygen at Observation (Surface) per Year")
dev.copy(png, "../output/env/simple_plots/oxygen_boxplot_surface_year.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

background points
Read in the presence points
background <- read.csv("../output/bio/background_complete_obs_cels_globot.csv", header = TRUE)
head(background)
environmental correlates
- Get the max, min, an mean values and add into a dataframe
Temperature
temp_depth_max_back <- max(background$temp_depth, na.rm = TRUE)
temp_depth_min_back <- min(background$temp_depth, na.rm = TRUE)
temp_depth_mean_back <- mean(background$temp_depth, na.rm = TRUE)
temp_surface_max_back <- max(background$temp_surface, na.rm = TRUE)
temp_surface_min_back <- min(background$temp_surface, na.rm = TRUE)
temp_surface_mean_back <- mean(background$temp_surface, na.rm = TRUE)
Salinity
sal_depth_max_back <- max(background$salinity_depth, na.rm = TRUE)
sal_depth_min_back <- min(background$salinity_depth, na.rm = TRUE)
sal_depth_mean_back <- mean(background$salinity_depth, na.rm = TRUE)
sal_surface_max_back <- max(background$salinity_surface, na.rm = TRUE)
sal_surface_min_back <- min(background$salinity_surface, na.rm = TRUE)
sal_surface_mean_back <- mean(background$salinity_surface, na.rm = TRUE)
Chl
chl_depth_max_back <- max(background$chl_depth, na.rm = TRUE)
chl_depth_min_back <- min(background$chl_depth, na.rm = TRUE)
chl_depth_mean_back <- mean(background$chl_depth, na.rm = TRUE)
chl_surface_max_back <- max(background$chl_surface, na.rm = TRUE)
chl_surface_min_back <- min(background$chl_surface, na.rm = TRUE)
chl_surface_mean_back <- mean(background$chl_surface, na.rm = TRUE)
O2
o2_depth_max_back <- max(background$o2_depth, na.rm = TRUE)
o2_depth_min_back <- min(background$o2_depth, na.rm = TRUE)
o2_depth_mean_back <- mean(background$o2_depth, na.rm = TRUE)
o2_surface_max_back <- max(background$o2_surface, na.rm = TRUE)
o2_surface_min_back <- min(background$o2_surface, na.rm = TRUE)
o2_surface_mean_back <- mean(background$o2_surface, na.rm = TRUE)
MLP
mlp_surface_max_back <- max(background$mlp_surface, na.rm = TRUE)
mlp_surface_min_back <- min(background$mlp_surface, na.rm = TRUE)
mlp_surface_mean_back <- mean(background$mlp_surface, na.rm = TRUE)
SSH
ssh_surface_max_back <- max(background$ssh_surface, na.rm = TRUE)
ssh_surface_min_back <- min(background$ssh_surface, na.rm = TRUE)
ssh_surface_mean_back <- mean(background$ssh_surface, na.rm = TRUE)
create matrix
tdb <- c(temp_depth_max_back, temp_depth_min_back, temp_depth_mean_back)
tsb <- c(temp_surface_max_back, temp_surface_min_back, temp_surface_mean_back)
sdb <- c(sal_depth_max_back, sal_depth_min_back, sal_depth_mean_back)
ssb <- c(sal_surface_max_back, sal_surface_min_back, sal_surface_mean_back)
cdb <- c(sal_depth_max_back, sal_depth_min_back, sal_depth_mean_back)
csb <- c(sal_surface_max_back, sal_surface_min_back, sal_surface_mean_back)
odb <- c(o2_depth_max_back, o2_depth_min_back, o2_depth_mean_back)
osb <- c(o2_surface_max_back, o2_surface_min_back, o2_surface_mean_back)
mlpb <- c(mlp_surface_max_back, mlp_surface_min_back, mlp_surface_mean_back)
sshb <- c(ssh_surface_max_back, ssh_surface_min_back, ssh_surface_mean_back)
env_stats_back <- rbind(tdb, tsb, sdb, ssb, cdb, csb, odb, osb, mlpb, sshb)
row.names(env_stats_back) <- c("Temp Depth", "Temp Surface", "Salinity Depth", "Salinity Surface", "Chl Depth", "Chl Surface", "Oxygen Depth", "Oxygen Surface", "MLP", "SSH")
colnames(env_stats_back) <- c("Max", "Min", "Mean")
write.csv(env_stats_back, "../output/env/env_correlates_background_basic_stats.csv", row.names = TRUE)
env_stats_back
Max Min Mean
Temp Depth 298.0517000 270.2798000 277.2492004
Temp Surface 298.2931000 271.0403000 278.9040097
Salinity Depth 36.2885400 12.8384380 33.3354335
Salinity Surface 35.9200800 12.0846500 32.3867768
Chl Depth 36.2885400 12.8384380 33.3354335
Chl Surface 35.9200800 12.0846500 32.3867768
Oxygen Depth 460.5706177 0.8061745 301.0655723
Oxygen Surface 410.5555000 207.4744000 315.9223887
MLP 2266.5013152 8.5859600 37.7989169
SSH -0.1283472 -1.2465040 -0.6931972
temperature
par(mfrow=c(1,2))
plot(background$temp_depth, main = "Background Points Temp at Depth (Various)", ylab = "Kelvin")
plot(background$temp_surface, main = "Background Points Temp at Surface", ylab = "Kelvin")
dev.copy(png, "../output/env/simple_plots/temperature_background_simpleplot.png") # to automatically save the plot to a png AND show it inline
png
salinity
par(mfrow=c(1,2))
plot(background$salinity_depth, main = "Background Points Salinity at Depth (Various)", ylab = "Practical Salinity Units")
plot(background$salinity_surface, main = "Background Points Salinity at Surface", ylab = "Practical Salinity Units")
dev.copy(png,"../output/env/simple_plots/salinity_background_simpleplot.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

Chlorophyll
par(mfrow=c(1,2))
plot(background$chl_depth, main = "Background Points Chl at Depth (Various)", ylab = "Chl (mmol.m-3)")
plot(background$chl_surface, main = "Background Points Chl at Surface", ylab = "Chl (mmol.m-3)")
dev.copy(png,"../output/env/simple_plots/chl_background_simpleplot.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

O2
par(mfrow=c(1,2))
plot(background$o2_depth, main = "Background Points Dissolved Oxygen at Depth (Various)", ylab = "Chl (mmol.m-3)")
plot(background$o2_surface, main = "Background Points Dissolved Oxygen at Surface", ylab = "O2 (mmol.m-3)")
dev.copy(png,"../output/env/simple_plots/o2_background_simpleplot.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

mlp
plot(background$mlp_surface, main = "Background Points Mixed Layer Thickness", ylab = "Depth (m)")
dev.copy(png,"../output/env/simple_plots/mlp_background_simpleplot.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

SSH
plot(background$ssh_surface, main = "Background Points Sea Surface Height", ylab = "Height (m)")
dev.copy(png,"../output/env/simple_plots/ssh_background_simpleplot.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

frequency plots of env. corr
temperature
hist(background$temp_surface, main = "Background Temp at Surface", xlab = "Kelvin")
dev.copy(png, "../output/env/simple_plots/temperature_background_surface_histogram.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

hist(background$temp_dept, main = "Background Temp at Depth", xlab = "Kelvin")
dev.copy(png, "../output/env/simple_plots/temperature_background_depth_histogram.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

chl
hist(background$chl_surface, main = "Background Chlorophyll at Surface", xlab = "Chlorophyll Concentrations (mmol.m-3)")
dev.copy(png, "../output/env/simple_plots/chl_background_surface_histogram.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

hist(background$chl_depth, main = "Background Chlorophyll at Observation Depth", xlab = "Chlorophyll Concentrations (mmol.m-3)")
dev.copy(png, "../output/env/simple_plots/chl_background_depth_histogram.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

salinity
hist(background$salinity_surface, main = "Background Salinity at Surface", xlab = "Salinity Practical Salinity Unit (PSU)")
dev.copy(png, "../output/env/simple_plots/sal_background_surface_histogram.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

hist(background$salinity_depth, main = "Background Salinity at Observation Depth", xlab = "Salinity Practical Salinity Unit (PSU)")
dev.copy(png, "../output/env/simple_plots/sal_background_depth_histogram.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

oxygen
hist(background$o2_surface, main = "Background Dissolved Oxygen at Surface", xlab = "Mole Concentration of Dissolved Oxygen in Sea Water (mmol.m-3)")
dev.copy(png, "../output/env/simple_plots/o2_background_surface_histogram.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

hist(background$o2_depth, main = "Background Dissolved Oxygen at Observation Depth", xlab = "Mole Concentration of Dissolved Oxygen in Sea Water (mmol.m-3)")
dev.copy(png, "../output/env/simple_plots/o2_background_depth_histogram.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

MLP
hist(background$mlp, main = "Background Mixed Layer Thickness at Observation", xlab = "Mixed Layer Thickness (m)")
dev.copy(png, "../output/env/simple_plots/mlp_background_surface_histogram.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ssh
hist(background$ssh, main = "Background Sea Surface Height at Observation", xlab = "Sea Surface Height (m)")
dev.copy(png, "../output/env/simple_plots/ssh_background_surface_histogram.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

simple boxplots of env. corr
Same as above but with boxplots (may provide some more useful info)
temperature
boxplot(background$temp_depth ~ background$month, xlab = "month", ylab = "Temperature (Kelvin)", main = "Temperature at Background Depth per Month")
dev.copy(png, "../output/env/simple_plots/temperature_background_boxplot_dept_month.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(background$chl_depth ~ background$month, xlab = "month", ylab = "Chlorophyll Concentrations (mmol.m-3)", main = "Chlorophyll at Background Depth per Month")
dev.copy(png, "../output/env/simple_plots/chlorophyll_background_boxplot_dept_month.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(background$salinity_depth ~ background$month, xlab = "month", ylab = "Salinity Practical Salinity Unit (PSU)", main = "Salinity at Background Depth per Month")
dev.copy(png, "../output/env/simple_plots/salinity_background_boxplot_dept_month.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(background$o2_depth ~ background$month, xlab = "month", ylab = "Mole Concentration of Dissolved Oxygen in Sea Water (mmol.m-3)", main = "Dissolved Oxygen at Background Depth per Month")
dev.copy(png, "../output/env/simple_plots/o2_background_boxplot_dept_month.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(background$mlp_surface ~ background$month, xlab = "month", ylab = "Mixed Layer Thickness (m)", main = "Mixed Layer Thickness at Background per Month")
dev.copy(png, "../output/env/simple_plots/mlp_background_boxplot_dept_month.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(background$ssh_surface ~ background$month, xlab = "month", ylab = "Sea Surface Height (m)", main = "Sea Surface Height at Background per Month")
dev.copy(png, "../output/env/simple_plots/ssh_background_boxplot_dept_month.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(background$temp_depth ~ background$year, xlab = "Year", ylab = "Temperature (Kelvin)", main = "Temperature at Background Depth per Year")
dev.copy(png, "../output/env/simple_plots/temperature_background_boxplot_dept_year.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(background$chl_depth ~ background$year, xlab = "Year", ylab = "Chlorophyll Concentrations (mmol.m-3)", main = "Chlorophyll at Background Depth per Year")
dev.copy(png, "../output/env/simple_plots/chl_background_boxplot_dept_year.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(background$salinity_depth ~ background$year, xlab = "Year", ylab = "Salinity Practical Salinity Unit (PSU)", main = "Salinity at Background Depth per Year")
dev.copy(png, "../output/env/simple_plots/salinity_background_boxplot_dept_year.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(background$o2_depth ~ background$year, xlab = "Year", ylab = "Mole Concentration of Dissolved Oxygen in Sea Water (mmol.m-3)", main = "Dissolved Oxygen at Background Depth per Year")
dev.copy(png, "../output/env/simple_plots/oxygen_background_boxplot_dept_year.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(background$mlp ~ background$year, xlab = "Year", ylab = "Mixed Layer Thickness (m)", main = "Mixed Layer Thickness at Background per Year")
dev.copy(png, "../output/env/simple_plots/mlp_background_boxplot_dept_year.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(background$ssh ~ background$year, xlab = "Year", ylab = "Sea Surface Height (m)", main = "Sea Surface Height at Background per Year")
dev.copy(png, "../output/env/simple_plots/ssh_background_boxplot_dept_year.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(background$temp_surface ~ background$month, xlab = "month", ylab = "Temperature (Kelvin)", main = "Temperature at Background (Surface) per Month")
dev.copy(png, "../output/env/simple_plots/temperature_background_boxplot_surface_month.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(background$chl_surface ~ background$month, xlab = "month", ylab = "Chlorophyll Concentrations (mmol.m-3)", main = "Chlorophyll at Background (Surface) per Month")
dev.copy(png, "../output/env/simple_plots/chlorophyll_background_boxplot_surface_month.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(background$salinity_surface ~ background$month, xlab = "month", ylab = "Salinity Practical Salinity Unit (PSU)", main = "Salinity at Background (Surface) per Month")
dev.copy(png, "../output/env/simple_plots/salinity_background_boxplot_surface_month.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(background$o2_surface ~ background$month, xlab = "month", ylab = "Mole Concentration of Dissolved Oxygen in Sea Water (mmol.m-3)", main = "Dissolved Oxygen at Background (Surface) per Month")
dev.copy(png, "../output/env/simple_plots/o2_background_boxplot_surface_month.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(background$mlp_surface ~ background$month, xlab = "month", ylab = "Mixed Layer Thickness (m)", main = "Mixed Layer Thickness at Background per Month")
dev.copy(png, "../output/env/simple_plots/mlp_background_boxplot_surface_month.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(background$ssh_surface ~ background$month, xlab = "month", ylab = "Sea Surface Height (m)", main = "Sea Surface Height at Background per Month")
dev.copy(png, "../output/env/simple_plots/ssh_background_boxplot_surface_month.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(background$temp_surface ~ background$year, xlab = "Year", ylab = "Temperature (Kelvin)", main = "Temperature at Background (Surface) per Year")
dev.copy(png, "../output/env/simple_plots/temperature_background_boxplot_surface_year.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(background$chl_surface ~ background$year, xlab = "Year", ylab = "Chlorophyll Concentrations (mmol.m-3)", main = "Chlorophyll at Background (Surface) per Year")
dev.copy(png, "../output/env/simple_plots/chl_background_boxplot_surface_year.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(background$salinity_surface ~ background$year, xlab = "Year", ylab = "Salinity Practical Salinity Unit (PSU)", main = "Salinity at Background (Surface) per Year")
dev.copy(png, "../output/env/simple_plots/salinity_background_boxplot_surface_year.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

boxplot(background$o2_surface ~ background$year, xlab = "Year", ylab = "Mole Concentration of Dissolved Oxygen in Sea Water (mmol.m-3)", main = "Dissolved Oxygen at Background (Surface) per Year")
dev.copy(png, "../output/env/simple_plots/oxygen_background_boxplot_surface_year.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

correlations between background points
check to see if there are any correlations in the env. variables for the background points
first subset the env.correlate columns (you don’t need everything)
background_env <- subset(background, select = c(amo_sample, amo_winter, amo_prev, nao_sample, nao_winter, nao_prev, chl_surface, chl_depth, mlp_surface, ssh_surface, temp_surface, temp_depth, o2_surface, o2_depth, salinity_surface, salinity_depth))
background_env_cor <- cor(background_env, use="complete.obs", method = "spearman") #need to create a correlation using cor to plot. complete.obs means na.rm in this package. #using spearmans as suitable for non-linear relationships
write.csv(background_env_cor, "../output/env/background_env_corr.csv", row.names = TRUE)
background_corrplot <- corrplot(background_env_cor , method = "color", type = "upper", order = "alphabet", tl.cex = 0.8)
dev.copy(png,"../output/env/simple_plots/background_envcorr.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

to get some density plots all in one graphic, you need to change chunk output to in console, then go to the plot tab, make it fill the screen, then run then make bigger then save :( (probably a better way - this seems to be an issue with RStudio)
par(mfrow=c(4,4))
for(i in 1:16){
plot(density(background_env[,i], na.rm=T), main = names(background_env)[i])
}

PUT THE CHUNK OUTPUT BACK TO INLINE
add nafo region and gear type into the mix
first subset the env.correlate columns + bottom_depth (you don’t need everything)
background_envbotdepth <- subset(background, select = c(amo_sample, amo_winter, amo_prev, nao_sample, nao_winter, nao_prev, chl_surface, chl_depth, mlp_surface, ssh_surface, temp_surface, temp_depth, o2_surface, o2_depth, salinity_surface, salinity_depth, bottom_depth))
background_envbotdepth_cor <- cor(background_envbotdepth, use="complete.obs", method = "spearman") #need to create a correlation using cor to plot. complete.obs means na.rm in this package. #using spearmans as suitable for non-linear relationships
write.csv(background_envbotdepth_cor, "../output/env/background_envbotdepth_cor.csv", row.names = TRUE)
background_corrplot <- corrplot(background_envbotdepth_cor , method = "color", type = "upper", order = "alphabet", tl.cex = 0.8)
dev.copy(png,"../output/env/simple_plots/background_envbotdepth_cor.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

correlations between presence points
check to see if there are any correlations in the env. variables
first subset the env.correlate columns (you don’t need everything) then use cor to get the correlation values, and then corrplot for a visual
pres_env <- subset(presence, select = c(amo_sample, amo_winter, amo_prev, nao_sample, nao_winter, nao_prev, chl_surface, chl_depth, mlp_surface, ssh_surface, temp_surface, temp_depth, o2_surface, o2_depth, salinity_surface, salinity_depth, bottom_depth))
pres_env_cor <- cor(pres_env, use="complete.obs", method = "spearman") #need to create a correlation using cor to plot. complete.obs means na.rm in this package. #using spearmans as suitable for non-linear relationships
write.csv(pres_env_cor, "../output/env/pres_env_corr.csv", row.names = TRUE)
pres_corrplot <- corrplot(pres_env_cor , method = "color", type = "upper", order = "alphabet", tl.cex = 0.8)
dev.copy(png,"../output/env/simple_plots/pres_envcorr.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

to get some density plots all in one graphic, you need to change chunk output to in console, then go to the plot tab, make it fill the screen, then run then make bigger then save :( (probably a better way - this seems to be an issue with RStudio)
graphics.off()
tiff("../output/env/simple_plots/background_envcorr_density.tiff") # to automatically save the plot to a png AND show it inline
par(mfrow=c(4,4), mar=c(1,1,1,1))
for(i in 1:16){
plot(density(pres_env[,i], na.rm=T), main = names(pres_env)[i])
}
dev.off() # stops automatic saving of the plot to a png
null device
1
PUT THE CHUNK OUTPUT BACK TO INLINE
density plot with background and presence env. data
Inspired by Merrow 2013 - top paragraph of page 1063 (are the species observations uniformly distributed over the background, or are they skewed)
ggplot(pres_env, aes(x = temp_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=background_env, na.rm = TRUE, colour = "blue")
dev.copy(png,"../output/env/simple_plots/temp_depth_backvspres.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(pres_env, aes(x = temp_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=background_env, na.rm = TRUE, colour = "blue")
dev.copy(png,"../output/env/simple_plots/temp_surface_backvspres.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(pres_env, aes(x = chl_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=background_env, na.rm = TRUE, colour = "blue")
dev.copy(png,"../output/env/simple_plots/chl_surface_backvspres.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(pres_env, aes(x = chl_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=background_env, na.rm = TRUE, colour = "blue")
dev.copy(png,"../output/env/simple_plots/chl_depth_backvspres.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(pres_env, aes(x = salinity_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=background_env, na.rm = TRUE, colour = "blue")
dev.copy(png,"../output/env/simple_plots/salinity_surface_backvspres.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(pres_env, aes(x = salinity_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=background_env, na.rm = TRUE, colour = "blue")
dev.copy(png,"../output/env/simple_plots/salinity_depth_backvspres.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(pres_env, aes(x = o2_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=background_env, na.rm = TRUE, colour = "blue")
dev.copy(png,"../output/env/simple_plots/o2_surface_backvspres.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(pres_env, aes(x = o2_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=background_env, na.rm = TRUE, colour = "blue")
dev.copy(png,"../output/env/simple_plots/o2_depth_backvspres.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(pres_env, aes(x = mlp_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=background_env, na.rm = TRUE, colour = "blue")
dev.copy(png,"../output/env/simple_plots/mlp_backvspres.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(pres_env, aes(x = ssh_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=background_env, na.rm = TRUE, colour = "blue")
dev.copy(png,"../output/env/simple_plots/ssh_backvspres.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

NAFO Regions
compare the environmental correlates between different NAFO regions
first see which nafo zones were sampled in each year
nafo_by_yr <- with(presence, table(year, nafo_zone))
write.csv(nafo_by_yr, file = "../output/bio/nafozone_by_yr.csv")
nafo_by_yr
nafo_zone
year 0A 0B 1C 2G 2H 2J 3K 3L 3M 3N 3O 3Pn 3Ps 4R 4S 4T 4Vn 4Vs 4W 4X 5Y 5Ze HudsonStrait
1998 0 0 0 0 12 56 113 230 0 44 69 3 58 0 0 70 9 7 4 3 1 0 0
1999 0 0 0 0 0 35 103 212 0 45 50 2 60 0 0 87 11 35 28 2 2 0 0
2000 0 0 0 0 0 55 116 238 2 52 53 4 48 0 0 99 12 26 20 1 0 0 0
2001 0 0 0 0 3 35 126 214 0 52 56 2 61 0 0 52 6 28 11 0 0 0 0
2002 0 0 0 0 0 36 71 214 0 50 62 4 60 0 0 110 8 28 16 1 0 0 0
2003 0 0 0 0 0 50 66 232 0 63 76 3 89 0 0 44 8 20 15 1 0 0 0
2004 0 0 0 0 8 60 209 194 0 58 66 7 69 40 70 160 10 11 5 1 0 0 0
2005 0 7 0 7 0 49 92 198 0 37 54 1 42 50 112 166 27 23 30 4 7 0 0
2006 3 4 0 3 14 49 175 178 0 25 26 0 19 28 132 148 11 39 31 9 7 1 0
2007 0 13 0 3 0 36 84 173 0 56 57 1 62 28 122 172 10 19 11 0 1 0 26
2008 3 7 0 0 6 49 82 162 0 46 57 0 77 64 129 157 5 18 13 3 0 2 0
2009 0 0 0 1 0 45 100 172 0 54 67 8 66 18 63 130 7 1 23 0 3 0 9
2010 0 9 1 0 6 34 111 207 0 62 63 3 50 16 56 134 12 18 14 0 0 0 0
2011 0 9 0 1 5 36 80 161 0 70 51 12 64 32 58 127 7 6 2 0 0 0 12
2012 0 7 0 1 0 0 0 0 0 0 0 0 0 34 71 133 5 1 3 1 0 0 0
2013 0 3 0 6 1 0 0 2 0 0 0 0 0 27 58 113 15 2 4 0 0 0 8
2014 1 16 0 1 0 0 0 1 0 0 0 0 0 0 0 101 6 0 0 0 0 0 4
2015 0 8 0 1 0 0 0 2 0 0 0 0 1 0 0 0 0 0 0 0 0 0 3
and by month
nafo_by_mth <- with(presence, table(nafo_zone, month))
write.csv(nafo_by_mth, file = "../output/bio/nafozone_by_mth.csv")
nafo_by_mth
month
nafo_zone 1 2 3 4 5 6 7 8 9 10 11 12
0A 0 0 0 0 0 0 0 3 0 3 1 0
0B 0 0 0 0 0 0 0 54 23 6 0 0
1C 0 0 0 0 0 0 0 1 0 0 0 0
2G 0 0 0 0 0 0 16 8 0 0 0 0
2H 0 0 0 0 0 0 2 0 0 50 0 3
2J 6 0 0 0 0 0 0 0 0 125 381 113
3K 255 4 0 0 0 0 0 2 0 0 610 657
3L 2 0 0 0 105 1410 83 1 0 64 764 361
3M 0 0 0 0 0 0 0 0 0 2 0 0
3N 0 0 0 0 308 254 0 0 0 110 40 2
3O 0 0 0 28 522 31 1 0 6 194 24 1
3Pn 0 0 0 42 8 0 0 0 0 0 0 0
3Ps 0 0 0 662 163 0 0 0 0 0 1 0
4R 0 0 0 0 0 0 18 318 1 0 0 0
4S 0 0 0 0 2 10 5 852 2 0 0 0
4T 0 0 0 0 15 14 10 570 1387 7 0 0
4Vn 0 0 0 1 0 0 145 8 15 0 0 0
4Vs 0 0 178 2 0 0 99 3 0 0 0 0
4W 0 6 163 11 0 0 44 4 0 1 1 0
4X 0 0 3 0 0 0 20 0 0 2 1 0
5Y 0 0 0 1 9 3 3 0 0 2 3 0
5Ze 0 1 2 0 0 0 0 0 0 0 0 0
HudsonStrait 0 0 0 0 0 0 1 7 0 54 0 0
Interesting that there is a point in 1C - this is outside Canadian waters…. anyway
density plot with background and presence env. data by NAFO region
What I want to see if if there is a marked difference between the env. correlates of the presence points between NAFO regions. This is also to try deal with sampling bias (b/c the whole region is not uniformly sampled in each month, but rather nafo regions have a strong month bias)
first create NAFO-region datasets
nafo0a <- subset(presence, nafo_zone == "0A")
nafo0b <- subset(presence, nafo_zone == "0B")
nafo1c <- subset(presence, nafo_zone == "1C")
nafo2g <- subset(presence, nafo_zone == "2G")
nafo2h <- subset(presence, nafo_zone == "2H")
nafo2j <- subset(presence, nafo_zone == "2J")
nafo3k <- subset(presence, nafo_zone == "3K")
nafo3l <- subset(presence, nafo_zone == "3L")
nafo3m <- subset(presence, nafo_zone == "3M")
nafo3n <- subset(presence, nafo_zone == "3N")
nafo3o <- subset(presence, nafo_zone == "3O")
nafo3ps <- subset(presence, nafo_zone == "3Ps")
nafo4r <- subset(presence, nafo_zone == "4R")
nafo4s <- subset(presence, nafo_zone == "4S")
nafo4t <- subset(presence, nafo_zone == "4T")
nafo4vn <- subset(presence, nafo_zone == "4Vn")
nafo4vs <- subset(presence, nafo_zone == "4Vs")
nafo4w <- subset(presence, nafo_zone == "4W")
nafo4x <- subset(presence, nafo_zone == "4X")
nafo5Y <- subset(presence, nafo_zone == "5Ze")
nafohudson <- subset(presence, nafo_zone == "HudsonStrait")
plot by each variable, less 3m (2 samples) 1c (one sample) and 5ze (zero samples?!)
ggplot(nafo0a, aes(x = o2_depth, colour = nafo_zone)) + geom_density(na.rm = TRUE) + geom_density(data=nafo0b, na.rm = TRUE) + geom_density(data=nafo2g, na.rm = TRUE) + geom_density(data=nafo2h, na.rm = TRUE) + geom_density(data=nafo2j, na.rm = TRUE) + geom_density(data=nafo3k, na.rm = TRUE) + geom_density(data=nafo3l, na.rm = TRUE) + geom_density(data=nafo3n, na.rm = TRUE) + geom_density(data=nafo3o, na.rm = TRUE) + geom_density(data=nafo3ps, na.rm = TRUE) + geom_density(data=nafo4r, na.rm = TRUE) + geom_density(data=nafo4s, na.rm = TRUE) + geom_density(data=nafo4t, na.rm = TRUE) + geom_density(data=nafo4vn, na.rm = TRUE) + geom_density(data=nafo4vs, na.rm = TRUE) + geom_density(data=nafo4w, na.rm = TRUE) + geom_density(data=nafo4x, na.rm = TRUE) + geom_density(data=nafo5y, na.rm = TRUE) + geom_density(data=nafohudson, na.rm = TRUE)
dev.copy(png,"../output/env/env_by_nafo_plots/o2_depth_nafo.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

Let’s plot the variables by nafo region/year then by month
pr98 <- subset(presence, year == "1998")
boxplot(pr98$temp_depth ~ pr98$nafo_zone, xlab = "NAFO Region", ylab = "Temperature (Kelvin)", main = "Temperature at Observation Depth per NAFO Zone")
pr98 <- subset(presence, year == "1998")
pr11 <- subset(presence, year == "2011")
par(mfrow=c(2,1))
boxplot(pr98$temp_depth ~ pr98$nafo_zone, xlab = "NAFO Region", ylab = "Temperature (Kelvin)", main = "Temperature at Observation Depth per NAFO Zone")
boxplot(pr11$temp_depth ~ pr11$nafo_zone, xlab = "NAFO Region", ylab = "Temperature (Kelvin)", main = "Temperature at Observation Depth per NAFO Zone")
ok scrap the nafo region analysis - it is too mixed up with month (so seeing if region or month is a factor that needs to be factored in to the model is not appropriate)
remap who sampled
Now lets check the number of records and spatial-temporal distribution of the observations by institution code to make sure none are dodgy
first a table of how many observations each instituioncode has
obs_by_ins <- count(presence, "institutioncode")
obs_by_ins
write.csv(obs_by_ins, file = "../output/bio/samplinginstitutions/no_observations_institutioncode.csv")
ok so IMR, NAFO, ICES, & USM have very few entries (1, 1, 1, and 3 respectively)
Lets take a look at the spatial breakdown of these institutions.First all points…
map2 <- getMap(resolution = "low") #creates an object called map at low resoultion
plot(map2, xlim = c(-70, -43), ylim =c(38, 70), asp = 1, main = "All Occurrences", col = "cornsilk") #the x and y lim are the long-lat bounds of the map
points(presence$decimalLongitude, presence$decimalLatitude, col = "red") #this adds points to the mapet", xlab = "Longitude", ylab = "Latitude")
dev.copy(png, "../output/bio/samplinginstitutions/all_occurrences.png") #this prints a png of the plot
dev.off() #this turns off the print command
Note there is one point up by iceland that you should get rid of (Icelandic population thought to be seperate from Labrador, but it is unclear if this is true or not).
Map the institutioncode == ARC only data…
ARC_obs <- presence[presence$institutioncode == "ARC", ]
map2 <- getMap(resolution = "low") #creates an object called map at low resoultion
plot(map2, xlim = c(-70, -43), ylim =c(39, 70), asp = 1, main = "Arc Occurrences", col = "cornsilk") #the x and y lim are the long-lat bounds of the map
points(ARC_obs$decimalLongitude, ARC_obs$decimalLatitude, col = "red") #this adds points to the mapet", xlab = "Longitude", ylab = "Latitude")
dev.copy(png, "../output/bio/samplinginstitutions/ARC_occurrences_all.png") #this prints a png of the plot
dev.off() #this turns off the print command
DFOCENARC_obs <- presence[presence$institutioncode == "DFOCENARC", ]
map2 <- getMap(resolution = "low") #creates an object called map at low resoultion
plot(map2, xlim = c(-70, -43), ylim =c(39, 70), asp = 1, main = "DFO Central & Arctic Occurrences", col = "cornsilk") #the x and y lim are the long-lat bounds of the map
points(DFOCENARC_obs$decimalLongitude, DFOCENARC_obs$decimalLatitude, col = "red") #this adds points to the mapet", xlab = "Longitude", ylab = "Latitude")
dev.copy(png, "../output/bio/samplinginstitutions/DFOCENARC_occurrences_all.png") #this prints a png of the plot
dev.off() #this turns off the print command
DFOGulf_obs <- presence[presence$institutioncode == "DFOGulf", ]
map2 <- getMap(resolution = "low") #creates an object called map at low resoultion
plot(map2, xlim = c(-70, -43), ylim =c(39, 70), asp = 1, main = "DFO Gulf Occurrences", col = "cornsilk") #the x and y lim are the long-lat bounds of the map
points(DFOGulf_obs$decimalLongitude, DFOGulf_obs$decimalLatitude, col = "red") #this adds points to the mapet", xlab = "Longitude", ylab = "Latitude")
dev.copy(png, "../output/bio/samplinginstitutions/DFOGulf_occurrences_all.png") #this prints a png of the plot
dev.off() #this turns off the print command
DFOISDM_obs <- presence[presence$institutioncode == "DFOISDM", ]
map2 <- getMap(resolution = "low") #creates an object called map at low resoultion
plot(map2, xlim = c(-70, -43), ylim =c(39, 70), asp = 1, main = "DFO ISDM Occurrences", col = "cornsilk") #the x and y lim are the long-lat bounds of the map
points(DFOISDM_obs$decimalLongitude, DFOISDM_obs$decimalLatitude, col = "red") #this adds points to the mapet", xlab = "Longitude", ylab = "Latitude")
dev.copy(png, "../output/bio/samplinginstitutions/DFOISDM_occurrences_all.png") #this prints a png of the plot
dev.off() #this turns off the print command
DFOMTMS_obs <- presence[presence$institutioncode == "DFOMTMS", ]
map2 <- getMap(resolution = "low") #creates an object called map at low resoultion
plot(map2, xlim = c(-70, -43), ylim =c(39, 70), asp = 1, main = "DFO Maritimes Occurrences", col = "cornsilk") #the x and y lim are the long-lat bounds of the map
points(DFOMTMS_obs$decimalLongitude, DFOMTMS_obs$decimalLatitude, col = "red") #this adds points to the mapet", xlab = "Longitude", ylab = "Latitude")
dev.copy(png, "../output/bio/samplinginstitutions/DFOMTMS_occurrences_all.png") #this prints a png of the plot
dev.off() #this turns off the print command
DFONL_obs <- presence[presence$institutioncode == "DFONL", ]
map2 <- getMap(resolution = "low") #creates an object called map at low resoultion
plot(map2, xlim = c(-70, -43), ylim =c(39, 70), asp = 1, main = "DFO Newfouundland & Labrador Occurrences", col = "cornsilk") #the x and y lim are the long-lat bounds of the map
points(DFONL_obs$decimalLongitude, DFONL_obs$decimalLatitude, col = "red") #this adds points to the mapet", xlab = "Longitude", ylab = "Latitude")
dev.copy(png, "../output/bio/samplinginstitutions/DFONL_occurrences_all.png") #this prints a png of the plot
dev.off() #this turns off the print command
DFOQC_obs <- presence[presence$institutioncode == "DFOQC", ]
map2 <- getMap(resolution = "low") #creates an object called map at low resoultion
plot(map2, xlim = c(-70, -43), ylim =c(39, 70), asp = 1, main = "DFO Quebec Occurrences", col = "cornsilk") #the x and y lim are the long-lat bounds of the map
points(DFOQC_obs$decimalLongitude, DFOQC_obs$decimalLatitude, col = "red") #this adds points to the mapet", xlab = "Longitude", ylab = "Latitude")
dev.copy(png, "../output/bio/samplinginstitutions/DFOQC_occurrences_all.png") #this prints a png of the plot
dev.off() #this turns off the print command
MaineDMR_obs <- presence[presence$institutioncode == "MaineDMR", ]
map2 <- getMap(resolution = "low") #creates an object called map at low resoultion
plot(map2, xlim = c(-70, -43), ylim =c(39, 70), asp = 1, main = "Maine DMR Occurrences", col = "cornsilk") #the x and y lim are the long-lat bounds of the map
points(MaineDMR_obs$decimalLongitude, MaineDMR_obs$decimalLatitude, col = "red") #this adds points to the mapet", xlab = "Longitude", ylab = "Latitude")
dev.copy(png, "../output/bio/samplinginstitutions/MaineDMR_occurrences_all.png") #this prints a png of the plot
dev.off() #this turns off the print command
NEFSC_obs <- presence[presence$institutioncode == "NEFSC", ]
map2 <- getMap(resolution = "low") #creates an object called map at low resoultion
plot(map2, xlim = c(-70, -43), ylim =c(39, 70), asp = 1, main = "NEFSC Occurrences", col = "cornsilk") #the x and y lim are the long-lat bounds of the map
points(NEFSC_obs$decimalLongitude, NEFSC_obs$decimalLatitude, col = "red") #this adds points to the mapet", xlab = "Longitude", ylab = "Latitude")
dev.copy(png, "../output/bio/samplinginstitutions/NEFSC_occurrences_all.png") #this prints a png of the plot
dev.off() #this turns off the print command
ROM_obs <- presence[presence$institutioncode == "ROM", ]
map2 <- getMap(resolution = "low") #creates an object called map at low resoultion
plot(map2, xlim = c(-70, -43), ylim =c(39, 70), asp = 1, main = "Royal Ontario Museum Occurrences", col = "cornsilk") #the x and y lim are the long-lat bounds of the map
points(ROM_obs$decimalLongitude, ROM_obs$decimalLatitude, col = "red") #this adds points to the mapet", xlab = "Longitude", ylab = "Latitude")
dev.copy(png, "../output/bio/samplinginstitutions/ROM_occurrences_all.png") #this prints a png of the plot
check for gear type
what are the unique gear types you have in your presence data, and how many?
so the vast majority are trawls of some type.
map the gear usage in Arcgis (gear_type_map)
create a table of gear use by month
gearby_mth
gear
month bottom_trawl bottom_trawl_alfredo_03 bottom_trawl_campelen_14 bottom_trawl_campelen_1800 bottom_trawl_campelen_21 bottom_trawl_cosmos_2600 bottom_trawl_western_IIA unknown
1 0 0 0 263 0 0 0 0
2 7 0 0 4 0 0 0 0
3 342 0 0 0 0 0 0 1
4 12 0 0 732 0 0 0 0
5 8 0 0 1106 0 0 0 18
6 3 0 0 1694 0 0 0 25
7 304 0 18 64 1 0 0 43
8 14 0 34 1193 36 3 7 543
9 0 0 0 12 23 0 1380 16
10 2 3 0 545 0 60 5 2
11 3 0 0 1811 0 1 0 8
12 0 0 0 1136 0 0 0 0
gear
month vertical_plankton_tow
1 0
2 0
3 3
4 3
5 0
6 0
7 17
8 1
9 3
10 3
11 3
12 1
What I want to see if if there is a marked difference between the env. correlates of the presence points between gear type used. This is also to try deal with detection bias between gear type (b/c the whole region is not uniformly sampled by the same gear type)
first create gear datasets
presence$gear <- as.character(presence$gear)
bottom_trawl <- subset(presence, gear == "bottom_trawl")
bottom_trawl_alfredo_03 <- subset(presence, gear == "bottom_trawl_alfredo_03")
bottom_trawl_campelen_14 <- subset(presence, gear == "bottom_trawl_campelen_14")
bottom_trawl_campelen_1800 <- subset(presence, gear == "bottom_trawl_campelen_1800")
bottom_trawl_campelen_21 <- subset(presence, gear == "bottom_trawl_campelen_21")
bottom_trawl_cosmos_2600 <- subset(presence, gear == "bottom_trawl_cosmos_2600")
bottom_trawl_western_IIA <- subset(presence, gear == "bottom_trawl_western_IIA")
unknown <- subset(presence, gear == "unknown")
vertical_plankton_tow <- subset(presence, gear == "vertical_plankton_tow")
plot by each variable, less 3m (2 samples) 1c (one sample) and 5ze (zero samples?!)
ggplot(bottom_trawl, aes(x = o2_depth, colour = gear)) + geom_density(na.rm = TRUE) + geom_density(data=bottom_trawl_alfredo_03, na.rm = TRUE) + geom_density(data=bottom_trawl_campelen_14, na.rm = TRUE) + geom_density(data=bottom_trawl_campelen_1800, na.rm = TRUE) + geom_density(data=bottom_trawl_campelen_21, na.rm = TRUE) + geom_density(data=bottom_trawl_cosmos_2600, na.rm = TRUE) + geom_density(data=bottom_trawl_western_IIA, na.rm = TRUE) + geom_density(data=unknown, na.rm = TRUE) + geom_density(data=vertical_plankton_tow, na.rm = TRUE)
dev.copy(png,"../output/env/env_by_gear_plots/o2_depth_gear.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

par(mar=c(7,5,1,1))
boxplot(presence$temp_depth ~ presence$gear, ylab = "Temperature (Kelvin)", main = "Temperature at Observation Depth by gear type", las = 2)
dev.copy(png, "../output/env/simple_plots/temperature_boxplot_dept_gear.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
looks like not much difference… what about a kruskal wallace test?
kruskal.test(presence$temp_depth ~ presence$gear)
Ok so there is a statistically sig difference somewhere in the temp at depth reported by the gear type (Kruskal-Wallis chi-squared = 248.27, df = 7, p-value < 2.2e-16)
To see where the difference(s) are run a Dunn test Zar (2010) states that the Dunn test (in the FSA package) is appropriate for groups with unequal numbers of observations.(Zar, J.H. 2010. Biostatistical Analysis, 5th ed. Pearson Prentice Hall: Upper Saddle River, NJ.) http://rcompanion.org/rcompanion/d_06.html
SAM WHEN DUNN IS INSTALLED, GO TO RCOMPANIONS.ORG AND LOOK FOR DUNN - CHECK CHROME HISTORY (PROBABLY UNDER KRUSKAL WALLIS) ALSO MAP THE DISTRIBUTION OF THESE GEAR TYPES
pairwise.wilcox.test(presence$temp_depth, presence$gear, p.adj='bonferroni', exact=F)
dunn test
gear_temp_depthdunn <- dunnTest(presence$temp_depth, presence$gear, list = TRUE)
gear_temp_depthdunn
write.csv(table, "../output/env/gear_temp_depthdunn.csv", row.names = TRUE)
vif
for this you need the joined dataset. this was created under mergig_datasets.src and the file is ../output/bio/presab.csv
presab <- read.csv("../output/bio/presab.csv", header = TRUE)
vif_allpresab <- vif(lm(occurrence ~ temp_surface + temp_depth + salinity_surface + salinity_depth + o2_surface + o2_depth + chl_surface + chl_depth + bottom_depth + mlp_surface + ssh_surface + gear + nao_sample + nao_prev + nao_winter + amo_sample + amo_prev + amo_winter, data = presab))
write.csv(vif_allpresab, "../output/bio/vif_allpresab.csv", row.names = TRUE)
vif_allpresab
interpret - see https://stats.stackexchange.com/questions/70679/which-variance-inflation-factor-should-i-be-using-textgvif-or-textgvif/96584#96584 To make GVIFs comparable across dimensions, we suggested using GVIF^(1/(2Df)), where Df is the number of coefficients in the subset (ref fox and motette 1992 in zotero) or the 2 continuous variables, GVIFˆ(1/(2Df)) (which is basically the square root of the VIF/GVIF value as DF=1) is the proportional change of the standard error and confidence interval of their coefficients due to the level of collinearity. The GVIFˆ(1/(2Df)) value of the categorical variable is a similar measure for the reduction in precision of the coefficients’ estimation due to collinearity. apparently i just need to square GVIF^(1/(2Df)) and then use the normal VIF “rule of thumb”…
vif_allpresab_sq <- read.csv("../output/bio/vif_allpresab.csv", header = TRUE)
vif_allpresab_sq$GVIF2Dfsq <- vif_allpresab_sq$GVIF..1..2.Df..^2
write.csv(vif_allpresab_sq, "../output/bio/vif_allpresab_sq.csv", row.names = TRUE)
vif_allpresab_sq
As per SLR suggestion, rerun without gear
vif_allbutgear <- vif(lm(occurrence ~ temp_surface + temp_depth + salinity_surface + salinity_depth + o2_surface + o2_depth + chl_surface + chl_depth + bottom_depth + mlp_surface + ssh_surface + nao_sample + nao_prev + nao_winter + amo_sample + amo_prev + amo_winter, data = presab))
write.csv(vif_allbutgear, "../output/bio/vif_allbutgear.csv", row.names = TRUE)
vif_allbutgear
As per SLR suggestion, rerun without gear and most highly correlated variables
vif_allbutgearhighlycorr <- vif(lm(occurrence ~ temp_surface + temp_depth + salinity_surface + salinity_depth + o2_depth + chl_surface + bottom_depth + mlp_surface + nao_sample + nao_prev + nao_winter + amo_sample + amo_winter, data = presab))
write.csv(vif_allbutgearhighlycorr, "../output/bio/vif_allbutgearhighlycorr.csv", row.names = TRUE)
vif_allbutgearhighlycorr
As per SLR suggestion, rerun with gear but without most highly correlated variables
vif_allbuthighlycorr <- vif(lm(occurrence ~ temp_surface + temp_depth + salinity_surface + salinity_depth + o2_depth + chl_surface + bottom_depth + mlp_surface + nao_sample + nao_prev + nao_winter + amo_sample + amo_winter + gear, data = presab))
write.csv(vif_allbuthighlycorr, "../output/bio/vif_allbuthighlycorr.csv", row.names = TRUE)
vif_allbuthighlycorr
vif_allbuthighlycorr_sq <- read.csv("../output/bio/vif_allbuthighlycorr.csv", header = TRUE)
vif_allbuthighlycorr_sq$GVIF2Dfsq <- vif_allbuthighlycorr_sq$GVIF..1..2.Df..^2
write.csv(vif_allbuthighlycorr_sq, "../output/bio/vif_allbuthighlycorr_sq.csv", row.names = TRUE)
vif_allbuthighlycorr_sq
ok remove one variable at a time - leave gear in
remove amo_prev
vif_allbutamo_prev <- vif(lm(occurrence ~ temp_surface + temp_depth + salinity_surface + salinity_depth + o2_surface + o2_depth + chl_surface + chl_depth + bottom_depth + mlp_surface + ssh_surface + gear + nao_sample + nao_prev + nao_winter + amo_sample + amo_winter, data = presab))
write.csv(vif_allbutamo_prev, "../output/bio/vif_allbutamo_prev.csv", row.names = TRUE)
vif_allbutamo_prev
vif_allbutamo_prev_sq <- read.csv("../output/bio/vif_allbutamo_prev.csv", header = TRUE)
vif_allbutamo_prev_sq$GVIF2Dfsq <- vif_allbutamo_prev_sq$GVIF..1..2.Df..^2
write.csv(vif_allbutamo_prev_sq, "../output/bio/vif_allbutamo_prev_sq.csv", row.names = TRUE)
vif_allbutamo_prev_sq
and leave gear out
remove amo_prev + gear
vif_allbutamo_prevgear <- vif(lm(occurrence ~ temp_surface + temp_depth + salinity_surface + salinity_depth + o2_surface + o2_depth + chl_surface + chl_depth + bottom_depth + mlp_surface + ssh_surface + nao_sample + nao_prev + nao_winter + amo_sample + amo_winter, data = presab))
write.csv(vif_allbutamo_prevgear, "../output/bio/vif_allbutamo_prevgear.csv", row.names = TRUE)
vif_allbutamo_prevgear
remove chl_depth
vif_allbutchl_depth <- vif(lm(occurrence ~ temp_surface + temp_depth + salinity_surface + salinity_depth + o2_surface + o2_depth + chl_surface + bottom_depth + mlp_surface + ssh_surface + gear + nao_sample + nao_prev + nao_winter + amo_sample + amo_prev + amo_winter, data = presab))
write.csv(vif_allbutchl_depth, "../output/bio/vif_allbutchl_depth.csv", row.names = TRUE)
vif_allbutchl_depth
vif_allbutchl_depth_sq <- read.csv("../output/bio/vif_allbutchl_depth.csv", header = TRUE)
vif_allbutchl_depth_sq$GVIF2Dfsq <- vif_allbutchl_depth_sq$GVIF..1..2.Df..^2
write.csv(vif_allbutchl_depth_sq, "../output/bio/vif_allbutchl_depth_sq.csv", row.names = TRUE)
vif_allbutchl_depth_sq
remove chl_depth and gear
vif_allbutchl_depthgear <- vif(lm(occurrence ~ temp_surface + temp_depth + salinity_surface + salinity_depth + o2_surface + o2_depth + chl_surface + bottom_depth + mlp_surface + ssh_surface + nao_sample + nao_prev + nao_winter + amo_sample + amo_prev + amo_winter, data = presab))
write.csv(vif_allbutchl_depthgear, "../output/bio/vif_allbutchl_depthgear.csv", row.names = TRUE)
vif_allbutchl_depthgear
remove ssh_surface
vif_allbutssh_surface <- vif(lm(occurrence ~ temp_surface + temp_depth + salinity_surface + salinity_depth + o2_surface + o2_depth + chl_surface + chl_depth + bottom_depth + mlp_surface + gear + nao_sample + nao_prev + nao_winter + amo_sample + amo_prev + amo_winter, data = presab))
write.csv(vif_allbutssh_surface, "../output/bio/vif_allbutssh_surface.csv", row.names = TRUE)
vif_allbutssh_surface
vif_allbutssh_surface_sq <- read.csv("../output/bio/vif_allbutssh_surface.csv", header = TRUE)
vif_allbutssh_surface_sq$GVIF2Dfsq <- vif_allbutssh_surface_sq$GVIF..1..2.Df..^2
write.csv(vif_allbutssh_surface_sq, "../output/bio/vif_allbutssh_surface_sq.csv", row.names = TRUE)
vif_allbutssh_surface_sq
remove ssh_surface & gear
vif_allbutssh_surfacegear <- vif(lm(occurrence ~ temp_surface + temp_depth + salinity_surface + salinity_depth + o2_surface + o2_depth + chl_surface + chl_depth + bottom_depth + mlp_surface + nao_sample + nao_prev + nao_winter + amo_sample + amo_prev + amo_winter, data = presab))
write.csv(vif_allbutssh_surfacegear, "../output/bio/vif_allbutssh_surfacegear.csv", row.names = TRUE)
vif_allbutssh_surfacegear
remove o2_surface
vif_allbuto2_surface <- vif(lm(occurrence ~ temp_surface + temp_depth + salinity_surface + salinity_depth + o2_depth + chl_surface + chl_depth + bottom_depth + mlp_surface + ssh_surface + gear + nao_sample + nao_prev + nao_winter + amo_sample + amo_prev + amo_winter, data = presab))
write.csv(vif_allbuto2_surface, "../output/bio/vif_allbuto2_surface.csv", row.names = TRUE)
vif_allbuto2_surface
vif_allbuto2_surface_sq <- read.csv("../output/bio/vif_allbuto2_surface.csv", header = TRUE)
vif_allbuto2_surface_sq$GVIF2Dfsq <- vif_allbuto2_surface_sq$GVIF..1..2.Df..^2
write.csv(vif_allbuto2_surface_sq, "../output/bio/vif_allbuto2_surface_sq.csv", row.names = TRUE)
vif_allbuto2_surface_sq
remove o2_surface & gear
vif_allbuto2_surfacegear <- vif(lm(occurrence ~ temp_surface + temp_depth + salinity_surface + salinity_depth + o2_depth + chl_surface + chl_depth + bottom_depth + mlp_surface + ssh_surface + nao_sample + nao_prev + nao_winter + amo_sample + amo_prev + amo_winter, data = presab))
write.csv(vif_allbuto2_surfacegear, "../output/bio/vif_allbuto2_surfacegear.csv", row.names = TRUE)
vif_allbuto2_surfacegear
as per SLR chat jan 23:
remove salinity_surface only
vif_allbutsalinitysurface <- vif(lm(occurrence ~ temp_surface + temp_depth + salinity_depth + o2_surface + o2_depth + chl_surface + chl_depth + bottom_depth + mlp_surface + ssh_surface + gear + nao_sample + nao_prev + nao_winter + amo_sample + amo_prev + amo_winter, data = presab))
write.csv(vif_allbutsalinitysurface, "../output/bio/vif_allbutsalinitysurface.csv", row.names = TRUE)
vif_allbutsalinitysurface
vif_allbutsalinitysurface_sq <- read.csv("../output/bio/vif_allbutsalinitysurface.csv", header = TRUE)
vif_allbutsalinitysurface_sq$GVIF2Dfsq <- vif_allbutsalinitysurface_sq$GVIF..1..2.Df..^2
write.csv(vif_allbutsalinitysurface_sq, "../output/bio/vif_allbutsalinitysurface_sq.csv", row.names = TRUE)
vif_allbutsalinitysurface_sq
and without gear
vif_allbutsalinitysurfacegear <- vif(lm(occurrence ~ temp_surface + temp_depth + salinity_depth + o2_surface + o2_depth + chl_surface + chl_depth + bottom_depth + mlp_surface + ssh_surface + nao_sample + nao_prev + nao_winter + amo_sample + amo_prev + amo_winter, data = presab))
write.csv(vif_allbutsalinitysurfacegear, "../output/bio/vif_allbutsalinitysurfacegear.csv", row.names = TRUE)
vif_allbutsalinitysurfacegear
now remove temp_surface plus highly correlated
#with gear
vif_allbuthighcorrtempsurface <- vif(lm(occurrence ~ temp_depth + salinity_surface + salinity_depth + o2_depth + chl_surface + bottom_depth + mlp_surface + gear + nao_sample + nao_prev + nao_winter + amo_sample + amo_winter, data = presab))
write.csv(vif_allbuthighcorrtempsurface, "../output/bio/vif_allbuthighcorrtempsurface.csv", row.names = TRUE)
vif_allbuthighcorrtempsurface
vif_allbuthighcorrtempsurface_sq <- read.csv("../output/bio/vif_allbuthighcorrtempsurface.csv", header = TRUE)
vif_allbuthighcorrtempsurface_sq$GVIF2Dfsq <- vif_allbuthighcorrtempsurface_sq$GVIF..1..2.Df..^2
write.csv(vif_allbuthighcorrtempsurface_sq, "../output/bio/vif_allbuthighcorrtempsurface_sq.csv", row.names = TRUE)
vif_allbuthighcorrtempsurface_sq
#without gear
vif_allbuthighcorrtempsurfacegear <- vif(lm(occurrence ~ temp_depth + salinity_surface + salinity_depth + o2_depth + chl_surface + bottom_depth + mlp_surface + nao_sample + nao_prev + nao_winter + amo_sample + amo_winter, data = presab))
write.csv(vif_allbuthighcorrtempsurfacegear, "../output/bio/vif_allbuthighcorrtempsurfacegear.csv", row.names = TRUE)
vif_allbuthighcorrtempsurfacegear
now remove temp_surface plus salinity_surface
#with gear
vif_allbuttempsalsurface <- vif(lm(occurrence ~ temp_depth + salinity_depth + o2_surface + o2_depth + chl_surface + chl_depth + bottom_depth + mlp_surface + ssh_surface + gear + nao_sample + nao_prev + nao_winter + amo_sample + amo_prev + amo_winter, data = presab))
write.csv(vif_allbuttempsalsurface, "../output/bio/vif_allbuttempsalsurface.csv", row.names = TRUE)
vif_allbuttempsalsurface
vif_allbuttempsalsurface_sq <- read.csv("../output/bio/vif_allbuttempsalsurface.csv", header = TRUE)
vif_allbuttempsalsurface_sq$GVIF2Dfsq <- vif_allbuttempsalsurface_sq$GVIF..1..2.Df..^2
write.csv(vif_allbuttempsalsurface_sq, "../output/bio/vif_allbuttempsalsurface_sq.csv", row.names = TRUE)
vif_allbuttempsalsurface_sq
#without gear
vif_allbuttempsalsurfacegear <- vif(lm(occurrence ~ temp_depth + salinity_depth + o2_surface + o2_depth + chl_surface + chl_depth + bottom_depth + mlp_surface + ssh_surface + nao_sample + nao_prev + nao_winter + amo_sample + amo_prev + amo_winter, data = presab))
write.csv(vif_allbuttempsalsurfacegear, "../output/bio/vif_allbuttempsalsurfacegear.csv", row.names = TRUE)
vif_allbuttempsalsurfacegear
now remove temp_surface plus salinity_surface + highly correlated
#with gear
vif_allbuthighcorrtempsalsurface <- vif(lm(occurrence ~ temp_depth + salinity_depth + o2_depth + chl_surface + bottom_depth + mlp_surface + gear + nao_sample + nao_prev + nao_winter + amo_sample + amo_winter, data = presab))
write.csv(vif_allbuthighcorrtempsalsurface, "../output/bio/vif_allbuthighcorrtempsalsurface.csv", row.names = TRUE)
vif_allbuthighcorrtempsalsurface
vif_allbuthighcorrtempsalsurface_sq <- read.csv("../output/bio/vif_allbuthighcorrtempsalsurface.csv", header = TRUE)
vif_allbuthighcorrtempsalsurface_sq$GVIF2Dfsq <- vif_allbuthighcorrtempsalsurface_sq$GVIF..1..2.Df..^2
write.csv(vif_allbuthighcorrtempsalsurface_sq, "../output/bio/vif_allbuthighcorrtempsalsurface_sq.csv", row.names = TRUE)
vif_allbuthighcorrtempsalsurface_sq
#without gear
vif_allbuthighcorrtempsalsurfacegear <- vif(lm(occurrence ~ temp_depth + salinity_depth + o2_depth + chl_surface + bottom_depth + mlp_surface + nao_sample + nao_prev + nao_winter + amo_sample + amo_winter, data = presab))
write.csv(vif_allbuthighcorrtempsalsurfacegear, "../output/bio/vif_allbuthighcorrtempsalsurfacegear.csv", row.names = TRUE)
vif_allbuthighcorrtempsalsurfacegear
Just out of curiosity, a vif will all but but atmos drivers
vif_allbutnaoamo <- vif(lm(occurrence ~ temp_surface + temp_depth + salinity_surface + salinity_depth + o2_surface + o2_depth + chl_surface + chl_depth + bottom_depth + mlp_surface + ssh_surface + gear, data = presab))
write.csv(vif_allbutnaoamo, "../output/bio/vif_allbutnaoamo.csv", row.names = TRUE)
vif_allbutnaoamo
vif_allbutnaoamo_sq <- read.csv("../output/bio/vif_allbutnaoamo.csv", header = TRUE)
vif_allbutnaoamo_sq$GVIF2Dfsq <- vif_allbutnaoamo_sq$GVIF..1..2.Df..^2
write.csv(vif_allbutnaoamo_sq, "../output/bio/vif_allbutnaoamo_sq.csv", row.names = TRUE)
vif_allbutnaoamo_sq
check to see how many cells have >1 point per timeslice
this needs to be 3D so you need to create a cell_id_3d
presab$cell_id_3d <- paste(presab$cell_id, presab$depthlayerno, sep="_") #create a new column that is a unique cell_id & depth ID.
head(presab)
and now do one with a timeslice label
write.csv(presab, "../output/bio/../output/bio/presab_cellid_xyzt.csv", row.names = FALSE)
cannot open file '../output/bio/../output/bio/presab_cellid_xyzt.csv': No such file or directoryError in file(file, ifelse(append, "a", "w")) :
cannot open the connection
because background points can land in the same xyzt, subset the dataset to be only presences
presencedup <- subset(presab, occurrence == "1")
nrow(presencedup)
[1] 11393
the data is in presencedup$total_cell_obs_xyzt
unique_pointpercell <- unique(presencedup$total_cell_obs_xyzt)
unique_pointpercell
[1] 1 3 2 4 5 6 15
bugger… ok so lets do a frequency table
so there are 949 3d timesliced cells that contain more than one occurrence, and 2042 rows. - different sampling days - different coordinates - risk of duplicate entries (but only if two instituions inputted the same data with slightly different coordinates and different reserch program names - see cell3985_18_2000_7 below as example)
cell3985_18_2000_7 <- subset(celobsmore1, cell_id_xyzt == "3985_18_2000_7")
cell3985_18_2000_7
Ideally you only want one observation cell cell_id_xyzt. First see if any are missing depth data
find the column numbers that correspond to the env. data (use fastmatch package as is quicker)
fmatch("chl_surface", names(celobsmore1)) #28
[1] 28
fmatch("chl_depth", names(celobsmore1)) #29
[1] 29
fmatch("mlp_surface", names(celobsmore1)) #30
[1] 30
fmatch("o2_surface", names(celobsmore1)) #31
[1] 31
fmatch("o2_depth", names(celobsmore1)) #32
[1] 32
fmatch("salinity_surface", names(celobsmore1)) #33
[1] 33
fmatch("salinity_depth", names(celobsmore1)) #34
[1] 34
fmatch("ssh_surface", names(celobsmore1)) #35
[1] 35
fmatch("temp_surface", names(celobsmore1)) #36
[1] 36
fmatch("temp_depth", names(celobsmore1)) #37
[1] 37
then subset any with NA values
celobsmore1_novals <- celobsmore1[!complete.cases(celobsmore1[28:37]), ] #28:37 represent the columns w/ env. data
nrow(celobsmore1_novals) #just to check how many there are - 1095 out of 2042
[1] 1095
ok and subset with all values
celobsmore1_allvals <- celobsmore1[complete.cases(celobsmore1[28:37]), ] #28:37 represent the columns w/ env. data
nrow(celobsmore1_allvals) #947 out of 2042
[1] 947
ok so how many unique cells do we have with complete data…
pointpercellcount_alldata <- count(celobsmore1_allvals, "total_cell_obs_xyzt")
pointpercellcount_alldata$no_cells <- pointpercellcount_alldata$freq / pointpercellcount_alldata$total_cell_obs_xyzt
write.csv(pointpercellcount_alldata, file = "../output/bio/pointpercellcount_alldata.csv")
pointpercellcount_alldata
and see which cell_id_xyzt appear in both celobsmore1_allvals and celobsmore1_novals
celobsmore1_allnovals <- inner_join(celobsmore1_allvals, celobsmore1_novals)
Joining, by = c("cell_id", "year", "month", "depthlayerno", "id", "decimalLatitude", "decimalLongitude", "datecollected", "institutioncode", "individualcount", "depth", "resname", "originalscientificname", "collectioncode", "day", "occurrence", "nafo_zone", "gear", "longitude_meters", "latitude_meters", "amo_sample", "amo_prev", "amo_winter", "depth_layer", "bottom_depth", "total_cell_obs_xy", "total_cell_obs_xyt", "chl_surface", "chl_depth", "mlp_surface", "o2_surface", "o2_depth", "salinity_surface", "salinity_depth", "ssh_surface", "temp_surface", "temp_depth", "nao_sample", "nao_prev", "nao_winter", "total_cell_obs_xyzt", "temp_celsius_depth", "temp_celsius_surface", "bottom_depth_glorys", "cell_id_3d", "cell_id_xyzt")
celobsmore1_allnovals
None…. which is good. I’d expect observations in the same xyzt to have the same values
so, I can successfully reduce the observations down to one per xyzt
obs_cell_yymm_depth_dup <- count(presab, cell_id, year, month, depthlayerno))
Error: unexpected ')' in "obs_cell_yymm_depth_dup <- count(presab, cell_id, year, month, depthlayerno))"
monthly spearmans correlations and VIF
curious - does correlations/vif alter between months?
First split the dataset into monthly
janpresab <- subset(presab, month == "1")
febpresab <- subset(presab, month == "2")
marpresab <- subset(presab, month == "3")
aprpresab <- subset(presab, month == "4")
maypresab <- subset(presab, month == "5")
junpresab <- subset(presab, month == "6")
julpresab <- subset(presab, month == "7")
augpresab <- subset(presab, month == "8")
seppresab <- subset(presab, month == "9")
octpresab <- subset(presab, month == "10")
novpresab <- subset(presab, month == "11")
decpresab <- subset(presab, month == "12")
now get the background points for each month (for spearmans)
janback <- subset(janpresab, occurrence == "0")
febback <- subset(febpresab, occurrence == "0")
marback <- subset(marpresab, occurrence == "0")
aprback <- subset(aprpresab, occurrence == "0")
mayback <- subset(maypresab, occurrence == "0")
junback <- subset(junpresab, occurrence == "0")
julback <- subset(julpresab, occurrence == "0")
augback <- subset(augpresab, occurrence == "0")
sepback <- subset(seppresab, occurrence == "0")
octback <- subset(octpresab, occurrence == "0")
novback <- subset(novpresab, occurrence == "0")
decback <- subset(decpresab, occurrence == "0")
run the correlations on each month’s background points
janback <- subset(janback, select = c(amo_sample, amo_winter, amo_prev, nao_sample, nao_winter, nao_prev, chl_surface, chl_depth, mlp_surface, ssh_surface, temp_surface, temp_depth, o2_surface, o2_depth, salinity_surface, salinity_depth))
janback_cor <- cor(janback, use="complete.obs", method = "spearman") #need to create a correlation using cor to plot. complete.obs means na.rm in this package. #using spearmans as suitable for non-linear relationships
write.csv(janback_cor, "../output/env/janback_cor.csv", row.names = TRUE)
febback <- subset(febback, select = c(amo_sample, amo_winter, amo_prev, nao_sample, nao_winter, nao_prev, chl_surface, chl_depth, mlp_surface, ssh_surface, temp_surface, temp_depth, o2_surface, o2_depth, salinity_surface, salinity_depth))
febback_cor <- cor(febback, use="complete.obs", method = "spearman") #need to create a correlation using cor to plot. complete.obs means na.rm in this package. #using spearmans as suitable for non-linear relationships
write.csv(febback_cor, "../output/env/febback_cor.csv", row.names = TRUE)
marback <- subset(marback, select = c(amo_sample, amo_winter, amo_prev, nao_sample, nao_winter, nao_prev, chl_surface, chl_depth, mlp_surface, ssh_surface, temp_surface, temp_depth, o2_surface, o2_depth, salinity_surface, salinity_depth))
marback_cor <- cor(marback, use="complete.obs", method = "spearman") #need to create a correlation using cor to plot. complete.obs means na.rm in this package. #using spearmans as suitable for non-linear relationships
write.csv(marback_cor, "../output/env/marback_cor.csv", row.names = TRUE)
aprback <- subset(aprback, select = c(amo_sample, amo_winter, amo_prev, nao_sample, nao_winter, nao_prev, chl_surface, chl_depth, mlp_surface, ssh_surface, temp_surface, temp_depth, o2_surface, o2_depth, salinity_surface, salinity_depth))
aprback_cor <- cor(aprback, use="complete.obs", method = "spearman") #need to create a correlation using cor to plot. complete.obs means na.rm in this package. #using spearmans as suitable for non-linear relationships
write.csv(aprback_cor, "../output/env/aprback_cor.csv", row.names = TRUE)
mayback <- subset(mayback, select = c(amo_sample, amo_winter, amo_prev, nao_sample, nao_winter, nao_prev, chl_surface, chl_depth, mlp_surface, ssh_surface, temp_surface, temp_depth, o2_surface, o2_depth, salinity_surface, salinity_depth))
mayback_cor <- cor(mayback, use="complete.obs", method = "spearman") #need to create a correlation using cor to plot. complete.obs means na.rm in this package. #using spearmans as suitable for non-linear relationships
write.csv(mayback_cor, "../output/env/mayback_cor.csv", row.names = TRUE)
junback <- subset(junback, select = c(amo_sample, amo_winter, amo_prev, nao_sample, nao_winter, nao_prev, chl_surface, chl_depth, mlp_surface, ssh_surface, temp_surface, temp_depth, o2_surface, o2_depth, salinity_surface, salinity_depth))
junback_cor <- cor(junback, use="complete.obs", method = "spearman") #need to create a correlation using cor to plot. complete.obs means na.rm in this package. #using spearmans as suitable for non-linear relationships
write.csv(junback_cor, "../output/env/junback_cor.csv", row.names = TRUE)
julback <- subset(julback, select = c(amo_sample, amo_winter, amo_prev, nao_sample, nao_winter, nao_prev, chl_surface, chl_depth, mlp_surface, ssh_surface, temp_surface, temp_depth, o2_surface, o2_depth, salinity_surface, salinity_depth))
julback_cor <- cor(julback, use="complete.obs", method = "spearman") #need to create a correlation using cor to plot. complete.obs means na.rm in this package. #using spearmans as suitable for non-linear relationships
write.csv(julback_cor, "../output/env/julback_cor.csv", row.names = TRUE)
augback <- subset(augback, select = c(amo_sample, amo_winter, amo_prev, nao_sample, nao_winter, nao_prev, chl_surface, chl_depth, mlp_surface, ssh_surface, temp_surface, temp_depth, o2_surface, o2_depth, salinity_surface, salinity_depth))
augback_cor <- cor(augback, use="complete.obs", method = "spearman") #need to create a correlation using cor to plot. complete.obs means na.rm in this package. #using spearmans as suitable for non-linear relationships
write.csv(augback_cor, "../output/env/augback_cor.csv", row.names = TRUE)
sepback <- subset(sepback, select = c(amo_sample, amo_winter, amo_prev, nao_sample, nao_winter, nao_prev, chl_surface, chl_depth, mlp_surface, ssh_surface, temp_surface, temp_depth, o2_surface, o2_depth, salinity_surface, salinity_depth))
sepback_cor <- cor(sepback, use="complete.obs", method = "spearman") #need to create a correlation using cor to plot. complete.obs means na.rm in this package. #using spearmans as suitable for non-linear relationships
write.csv(sepback_cor, "../output/env/sepback_cor.csv", row.names = TRUE)
octback <- subset(octback, select = c(amo_sample, amo_winter, amo_prev, nao_sample, nao_winter, nao_prev, chl_surface, chl_depth, mlp_surface, ssh_surface, temp_surface, temp_depth, o2_surface, o2_depth, salinity_surface, salinity_depth))
octback_cor <- cor(octback, use="complete.obs", method = "spearman") #need to create a correlation using cor to plot. complete.obs means na.rm in this package. #using spearmans as suitable for non-linear relationships
write.csv(octback_cor, "../output/env/octback_cor.csv", row.names = TRUE)
novback <- subset(novback, select = c(amo_sample, amo_winter, amo_prev, nao_sample, nao_winter, nao_prev, chl_surface, chl_depth, mlp_surface, ssh_surface, temp_surface, temp_depth, o2_surface, o2_depth, salinity_surface, salinity_depth))
novback_cor <- cor(novback, use="complete.obs", method = "spearman") #need to create a correlation using cor to plot. complete.obs means na.rm in this package. #using spearmans as suitable for non-linear relationships
write.csv(novback_cor, "../output/env/novback_cor.csv", row.names = TRUE)
decback <- subset(decback, select = c(amo_sample, amo_winter, amo_prev, nao_sample, nao_winter, nao_prev, chl_surface, chl_depth, mlp_surface, ssh_surface, temp_surface, temp_depth, o2_surface, o2_depth, salinity_surface, salinity_depth))
decback_cor <- cor(decback, use="complete.obs", method = "spearman") #need to create a correlation using cor to plot. complete.obs means na.rm in this package. #using spearmans as suitable for non-linear relationships
write.csv(decback_cor, "../output/env/decback_cor.csv", row.names = TRUE)
maxent?
library("raster")
library("dismo")
library("rgeos")
LS0tDQp0aXRsZTogIkRhdGEgRXhwbG9yYXRpb24iDQphdXRob3I6ICJTYW1hbnRoYSBBbmRyZXdzIg0Kb3V0cHV0OiANCiAgaHRtbF9ub3RlYm9vazogDQogICAgZmlnX2hlaWdodDogNw0KICAgIGZpZ193aWR0aDogMTANCmVkaXRvcl9vcHRpb25zOiANCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZQ0KLS0tDQoNCiMgT3ZlcnZpZXcNCkV4cGxvcmF0aW9uIG9mIGFsbCB0aGUgZGF0YSBjb2xsZWN0ZWQgb24gdGhlIHByZXNlbmNlIHBvaW50cyArIHJhbmRvbWx5IGdlbmVyYXRlZCBiYWNrZ3JvdW5kIHBvaW50cw0KDQpBIG5vdGUgdG8gYW55b25lIHdobyBtaWdodCBoYXBwZW4gdG8gc3R1bWJsZSBhY3Jvc3MgdGhpcy4uLiBJIGFtIGEgYmVnaW5uZXIgaW4gUiBhbmQgaGF2ZSBoYWQgbm8gZXhwb3N1cmUgdG8gc2ltaWxhciBsYW5ndWFnZXMuIEkgZG9uJ3Qga25vdyB3aGF0IEknbSBkb2luZy4gVGhlIGNvZGUgaGVyZWluIGlzIHVubGlrZWx5IHRvIGJlIGVsZWdhbnQgYW5kIHRoZXJlIGFyZSBwcm9iYWJseSBtb3JlIGVmZmljaWVudCB3YXlzIG9mIHJ1bm5pbmcgdGhlIGNvZGUuDQoNCkJ1aWx0IHdpdGggJ3IgZ2V0UnZlcnNpb24oKScuDQoNCiMgUGFja2FnZSBkZXBlbmRlbmNpZXMNCllvdSBjYW4gbG9hZCB0aGVtIHVzaW5nIHRoZSBmb2xsb3dpbmcgY29kZSB3aGljaCB1c2VzIGEgZnVuY3Rpb24gY2FsbGVkIFtpcGFrXShodHRwczovL2dpc3QuZ2l0aHViLmNvbS9zdGV2ZW53b3J0aGluZ3Rvbi8zMTc4MTYzKS4gDQpOb3RlIHRoaXMgZnVuY3Rpb24gY2hlY2tzIHRvIHNlZSBpZiB0aGUgcGFja2FnZXMgYXJlIGluc3RhbGxlZCBmaXJzdC4NClRoZSAiaW5jbHVkZT1GQUxTRSIgc3VwcmVzc2VzIHRoZSBwYWNrYWdlIGluc3RhbGxhdGlvbiB0ZXh0IGFwcGVhcmluZyBpbiB0aGUgZG9jdW1lbnQuLi4NCmBgYHtyIHByZS1pbnN0YWxsIHBhY2thZ2VzLCBpbmNsdWRlPUZBTFNFfQ0KcGFja2FnZXMgPC0gYygicGx5ciIsICJncmFwaGljcyIsICJnZ3Bsb3QyIiwgImNvcnJwbG90IiwgIkZTQSIsICJjYXIiLCAicndvcmxkbWFwIiwgImZhc3RtYXRjaCIpIA0Kc291cmNlKCIuLi9zcmMvaXBhay5SIikNCmlwYWsocGFja2FnZXMpDQpgYGANCg0KDQojIHByZXNlbmNlIHBvaW50cw0KUmVhZCBpbiB0aGUgcHJlc2VuY2UgcG9pbnRzDQoNCmBgYHtyfQ0KcHJlc2VuY2UgPC0gcmVhZC5jc3YoIi4uL291dHB1dC9iaW8vcHJlc2VuY2VfcG9pbnRzX3dpdGhvdXRfZW52ZGF0YV9yZWxvb3BlZF9nbGJhdGh5LmNzdiIsIGhlYWRlciA9IFRSVUUpDQpoZWFkKHByZXNlbmNlKQ0KYGBgDQoNCiMjIFVwZGF0ZTogV2hvIHNhbXBsZWQgaW4gd2hpY2ggeWVhciBhbmQgd2hpY2ggbW9udGg6DQoNCnllYXINCmBgYHtyfQ0KaW5zdF9ieV95ciA8LSB3aXRoKHByZXNlbmNlLCB0YWJsZSh5ZWFyLCBpbnN0aXR1dGlvbmNvZGUpKQ0Kd3JpdGUuY3N2KGluc3RfYnlfeXIsIGZpbGUgPSAiLi4vb3V0cHV0L2Jpby9pbnN0aXR1dGlvbmNvZGVfYnlfeXIuY3N2IikNCmluc3RfYnlfeXINCmBgYA0KDQptb250aA0KYGBge3J9DQppbnN0X2J5X210IDwtIHdpdGgocHJlc2VuY2UsIHRhYmxlKG1vbnRoLCBpbnN0aXR1dGlvbmNvZGUpKQ0Kd3JpdGUuY3N2KGluc3RfYnlfbXQsIGZpbGUgPSAiLi4vb3V0cHV0L2Jpby9pbnN0aXR1dGlvbmNvZGVfYnlfbXRoLmNzdiIpDQppbnN0X2J5X210DQpgYGANCg0KIyMgZW52aXJvbm1lbnRhbCBjb3JyZWxhdGVzDQoNCjEpIEdldCB0aGUgbWF4LCBtaW4sIGFuIG1lYW4gdmFsdWVzIGFuZCBhZGQgaW50byBhIGRhdGFmcmFtZQ0KDQpUZW1wZXJhdHVyZQ0KYGBge3J9DQp0ZW1wX2RlcHRoX21heCA8LSBtYXgocHJlc2VuY2UkdGVtcF9kZXB0aCwgbmEucm0gPSBUUlVFKQ0KdGVtcF9kZXB0aF9taW4gPC0gbWluKHByZXNlbmNlJHRlbXBfZGVwdGgsIG5hLnJtID0gVFJVRSkNCnRlbXBfZGVwdGhfbWVhbiA8LSBtZWFuKHByZXNlbmNlJHRlbXBfZGVwdGgsIG5hLnJtID0gVFJVRSkNCnRlbXBfc3VyZmFjZV9tYXggPC0gbWF4KHByZXNlbmNlJHRlbXBfc3VyZmFjZSwgbmEucm0gPSBUUlVFKQ0KdGVtcF9zdXJmYWNlX21pbiA8LSBtaW4ocHJlc2VuY2UkdGVtcF9zdXJmYWNlLCBuYS5ybSA9IFRSVUUpDQp0ZW1wX3N1cmZhY2VfbWVhbiA8LSBtZWFuKHByZXNlbmNlJHRlbXBfc3VyZmFjZSwgbmEucm0gPSBUUlVFKQ0KYGBgDQoNClNhbGluaXR5DQpgYGB7cn0NCnNhbF9kZXB0aF9tYXggPC0gbWF4KHByZXNlbmNlJHNhbGluaXR5X2RlcHRoLCBuYS5ybSA9IFRSVUUpDQpzYWxfZGVwdGhfbWluIDwtIG1pbihwcmVzZW5jZSRzYWxpbml0eV9kZXB0aCwgbmEucm0gPSBUUlVFKQ0Kc2FsX2RlcHRoX21lYW4gPC0gbWVhbihwcmVzZW5jZSRzYWxpbml0eV9kZXB0aCwgbmEucm0gPSBUUlVFKQ0Kc2FsX3N1cmZhY2VfbWF4IDwtIG1heChwcmVzZW5jZSRzYWxpbml0eV9zdXJmYWNlLCBuYS5ybSA9IFRSVUUpDQpzYWxfc3VyZmFjZV9taW4gPC0gbWluKHByZXNlbmNlJHNhbGluaXR5X3N1cmZhY2UsIG5hLnJtID0gVFJVRSkNCnNhbF9zdXJmYWNlX21lYW4gPC0gbWVhbihwcmVzZW5jZSRzYWxpbml0eV9zdXJmYWNlLCBuYS5ybSA9IFRSVUUpDQpgYGANCg0KQ2hsDQpgYGB7cn0NCmNobF9kZXB0aF9tYXggPC0gbWF4KHByZXNlbmNlJGNobF9kZXB0aCwgbmEucm0gPSBUUlVFKQ0KY2hsX2RlcHRoX21pbiA8LSBtaW4ocHJlc2VuY2UkY2hsX2RlcHRoLCBuYS5ybSA9IFRSVUUpDQpjaGxfZGVwdGhfbWVhbiA8LSBtZWFuKHByZXNlbmNlJGNobF9kZXB0aCwgbmEucm0gPSBUUlVFKQ0KY2hsX3N1cmZhY2VfbWF4IDwtIG1heChwcmVzZW5jZSRjaGxfc3VyZmFjZSwgbmEucm0gPSBUUlVFKQ0KY2hsX3N1cmZhY2VfbWluIDwtIG1pbihwcmVzZW5jZSRjaGxfc3VyZmFjZSwgbmEucm0gPSBUUlVFKQ0KY2hsX3N1cmZhY2VfbWVhbiA8LSBtZWFuKHByZXNlbmNlJGNobF9zdXJmYWNlLCBuYS5ybSA9IFRSVUUpDQpgYGANCg0KTzINCmBgYHtyfQ0KbzJfZGVwdGhfbWF4IDwtIG1heChwcmVzZW5jZSRvMl9kZXB0aCwgbmEucm0gPSBUUlVFKQ0KbzJfZGVwdGhfbWluIDwtIG1pbihwcmVzZW5jZSRvMl9kZXB0aCwgbmEucm0gPSBUUlVFKQ0KbzJfZGVwdGhfbWVhbiA8LSBtZWFuKHByZXNlbmNlJG8yX2RlcHRoLCBuYS5ybSA9IFRSVUUpDQpvMl9zdXJmYWNlX21heCA8LSBtYXgocHJlc2VuY2UkbzJfc3VyZmFjZSwgbmEucm0gPSBUUlVFKQ0KbzJfc3VyZmFjZV9taW4gPC0gbWluKHByZXNlbmNlJG8yX3N1cmZhY2UsIG5hLnJtID0gVFJVRSkNCm8yX3N1cmZhY2VfbWVhbiA8LSBtZWFuKHByZXNlbmNlJG8yX3N1cmZhY2UsIG5hLnJtID0gVFJVRSkNCmBgYA0KDQpNTFANCmBgYHtyfQ0KbWxwX3N1cmZhY2VfbWF4IDwtIG1heChwcmVzZW5jZSRtbHBfc3VyZmFjZSwgbmEucm0gPSBUUlVFKQ0KbWxwX3N1cmZhY2VfbWluIDwtIG1pbihwcmVzZW5jZSRtbHBfc3VyZmFjZSwgbmEucm0gPSBUUlVFKQ0KbWxwX3N1cmZhY2VfbWVhbiA8LSBtZWFuKHByZXNlbmNlJG1scF9zdXJmYWNlLCBuYS5ybSA9IFRSVUUpDQpgYGANCg0KU1NIDQpgYGB7cn0NCnNzaF9zdXJmYWNlX21heCA8LSBtYXgocHJlc2VuY2Ukc3NoX3N1cmZhY2UsIG5hLnJtID0gVFJVRSkNCnNzaF9zdXJmYWNlX21pbiA8LSBtaW4ocHJlc2VuY2Ukc3NoX3N1cmZhY2UsIG5hLnJtID0gVFJVRSkNCnNzaF9zdXJmYWNlX21lYW4gPC0gbWVhbihwcmVzZW5jZSRzc2hfc3VyZmFjZSwgbmEucm0gPSBUUlVFKQ0KYGBgDQoNCmNyZWF0ZSBtYXRyaXgNCmBgYHtyfQ0KdGQgPC0gYyh0ZW1wX2RlcHRoX21heCwgdGVtcF9kZXB0aF9taW4sIHRlbXBfZGVwdGhfbWVhbikNCnRzIDwtIGModGVtcF9zdXJmYWNlX21heCwgdGVtcF9zdXJmYWNlX21pbiwgdGVtcF9zdXJmYWNlX21lYW4pDQpzZCA8LSBjKHNhbF9kZXB0aF9tYXgsIHNhbF9kZXB0aF9taW4sIHNhbF9kZXB0aF9tZWFuKQ0Kc3MgPC0gYyhzYWxfc3VyZmFjZV9tYXgsIHNhbF9zdXJmYWNlX21pbiwgc2FsX3N1cmZhY2VfbWVhbikNCmNkIDwtIGMoc2FsX2RlcHRoX21heCwgc2FsX2RlcHRoX21pbiwgc2FsX2RlcHRoX21lYW4pDQpjcyA8LSBjKHNhbF9zdXJmYWNlX21heCwgc2FsX3N1cmZhY2VfbWluLCBzYWxfc3VyZmFjZV9tZWFuKQ0Kb2QgPC0gYyhvMl9kZXB0aF9tYXgsIG8yX2RlcHRoX21pbiwgbzJfZGVwdGhfbWVhbikNCm9zIDwtIGMobzJfc3VyZmFjZV9tYXgsIG8yX3N1cmZhY2VfbWluLCBvMl9zdXJmYWNlX21lYW4pDQptbHAgPC0gYyhtbHBfc3VyZmFjZV9tYXgsIG1scF9zdXJmYWNlX21pbiwgbWxwX3N1cmZhY2VfbWVhbikNCnNzaCA8LSBjKHNzaF9zdXJmYWNlX21heCwgc3NoX3N1cmZhY2VfbWluLCBzc2hfc3VyZmFjZV9tZWFuKQ0KZW52X3N0YXRzIDwtIHJiaW5kKHRkLCB0cywgc2QsIHNzLCBjZCwgY3MsIG9kLCBvcywgbWxwLCBzc2gpDQpyb3cubmFtZXMoZW52X3N0YXRzKSA8LSBjKCJUZW1wIERlcHRoIiwgIlRlbXAgU3VyZmFjZSIsICJTYWxpbml0eSBEZXB0aCIsICJTYWxpbml0eSBTdXJmYWNlIiwgIkNobCBEZXB0aCIsICJDaGwgU3VyZmFjZSIsICJPeHlnZW4gRGVwdGgiLCAiT3h5Z2VuIFN1cmZhY2UiLCAiTUxQIiwgIlNTSCIpIA0KY29sbmFtZXMoZW52X3N0YXRzKSA8LSBjKCJNYXgiLCAiTWluIiwgIk1lYW4iKQ0Kd3JpdGUuY3N2KGVudl9zdGF0cywgIi4uL291dHB1dC9lbnYvZW52X2NvcnJlbGF0ZXNfYmFzaWNfc3RhdHMuY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkNCmVudl9zdGF0cw0KYGBgDQoNCkhtbSBzb21lIHBvdGVudGlhbGx5IHN1c3BpY2lvdXMgdmFsdWVzIGhlcmUgaW4NCi0gT3h5Z2VuIERlcHRoIG1pbg0KLSBtbHAgIE1heA0KYW5kIG1heWJlIGFsc28NCi0gU2FsaW5pdHkgRGVwdGggbWluDQotIFNhbGluaXR5IFN1cmZhY2UgbWluDQotIENITCBkZXB0aCBtaW4NCi0gQ0hMIGRlcHRoIG1heA0KDQpsZXRzIGp1c3Qgc2VlIHdoZXJlIHRoZXNlIHZhbHVlcyBhcHBlYXIgYW5kIGNoZWNrIHRoZSBuZXRjZGYgbGF5ZXJzLiBOb3RlIEkgd2lsbCBjaGVjayB0aGVzZSB2YWx1ZXMgaW4gY3lnd2luIHVzaW5nIHRoZSBjZG8gb3BlcmF0b3IgaW5mb3Ygb24gdGhlIG5ldGNkZnMgKHRvIGVuc3VyZSB0aGVyZSB3YXMgbm8gaXNzdWUgd2l0aCBwcm9jZXNzaW5nIGluIFIpLiANCg0KDQpnZXQgdGhlIHllYXIgYW5kIG1vbnRoIHRoZXNlIHZhbHVlcyBhcHBlYXJlZCBpbg0KYGBge3J9DQpvMmRfY2hlY2tfeXIgPC0gc3Vic2V0KHByZXNlbmNlJHllYXIsIHByZXNlbmNlJG8yX2RlcHRoID09IG8yX2RlcHRoX21pbikNCm8yZF9jaGVja19tdGggPC0gc3Vic2V0KHByZXNlbmNlJG1vbnRoLCBwcmVzZW5jZSRvMl9kZXB0aCA9PSBvMl9kZXB0aF9taW4pDQpgYGANCk8yIGRlcHRoIG1pbiBpcyBpbiAyMDA1XzA4DQoNCkFuZCB2YWx1ZSBzZWVtcyBjb3JyZWN0DQoNCmBgYHtyfQ0KbWxwX2NoZWNrX3lyIDwtIHN1YnNldChwcmVzZW5jZSR5ZWFyLCBwcmVzZW5jZSRtbHBfc3VyZmFjZSA9PSBtbHBfc3VyZmFjZV9tYXgpDQptbHBfY2hlY2tfbXRoIDwtIHN1YnNldChwcmVzZW5jZSRtb250aCwgcHJlc2VuY2UkbWxwX3N1cmZhY2UgPT0gbWxwX3N1cmZhY2VfbWF4KQ0KYGBgDQptbHAgbWF4IGluIGluIDIwMDdfMTINCg0KQW5kIHllcyB0aGUgdmFsdWUgc2VlbXMgY29ycmVjdA0KDQpgYGB7cn0NCnNhbGRfY2hlY2tfeXIgPC0gc3Vic2V0KHByZXNlbmNlJHllYXIsIHByZXNlbmNlJHNhbGluaXR5X2RlcHRoID09IHNhbF9kZXB0aF9tYXgpDQpzYWxkX2NoZWNrX210aCA8LSBzdWJzZXQocHJlc2VuY2UkbW9udGgsIHByZXNlbmNlJHNhbGluaXR5X2RlcHRoID09IHNhbF9kZXB0aF9tYXgpDQpgYGANCnllYXIgbW9udGggMjAwMV8wNQ0KDQphbHNvIHNlZW1zIGNvcnJlY3QNCg0KYGBge3J9DQpzYWxzX2NoZWNrX3lyIDwtIHN1YnNldChwcmVzZW5jZSR5ZWFyLCBwcmVzZW5jZSRzYWxpbml0eV9zdXJmYWNlID09IHNhbF9zdXJmYWNlX21pbikNCnNhbHNfY2hlY2tfbXRoIDwtIHN1YnNldChwcmVzZW5jZSRtb250aCwgcHJlc2VuY2Ukc2FsaW5pdHlfc3VyZmFjZSA9PSBzYWxfc3VyZmFjZV9taW4pDQpgYGANCnllYXIgbW9udGggMjE5OThfMDYNCg0Kb2sgYWdhaW4uLi4NCg0KTGVhdmUgdGhlIHJlc3QNCg0KDQojIyBzaW1wbGUgcGxvdHMgb2YgZW52LiBjb3JyZWxhdGVzDQoNCnRlbXBlcmF0dXJlDQpgYGB7cn0NCnBhcihtZnJvdz1jKDEsMikpDQpwbG90KHByZXNlbmNlJHRlbXBfZGVwdGgsIG1haW4gPSAiVGVtcCBhdCBEZXB0aCAoVmFyaW91cykiLCB5bGFiID0gIktlbHZpbiIpDQpwbG90KHByZXNlbmNlJHRlbXBfc3VyZmFjZSwgbWFpbiA9ICJUZW1wIGF0IFN1cmZhY2UiLCB5bGFiID0gIktlbHZpbiIpDQpkZXYuY29weShwbmcsICIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy90ZW1wZXJhdHVyZV9zaW1wbGVwbG90LnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQpIbW0gbm90IG5lY2Vzc2FyaWx5IHZlcnkgaGVscGZ1bC4gQnV0IGFueXdheSwgbGV0cyBjYXJyeSBvbg0KDQpzYWxpbml0eQ0KYGBge3J9DQpwYXIobWZyb3c9YygxLDIpKQ0KcGxvdChwcmVzZW5jZSRzYWxpbml0eV9kZXB0aCwgbWFpbiA9ICJTYWxpbml0eSBhdCBEZXB0aCAoVmFyaW91cykiLCB5bGFiID0gIlByYWN0aWNhbCBTYWxpbml0eSBVbml0cyIpDQpwbG90KHByZXNlbmNlJHNhbGluaXR5X3N1cmZhY2UsIG1haW4gPSAiU2FsaW5pdHkgYXQgU3VyZmFjZSIsIHlsYWIgPSAiUHJhY3RpY2FsIFNhbGluaXR5IFVuaXRzIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9zaW1wbGVfcGxvdHMvc2FsaW5pdHlfc2ltcGxlcGxvdC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpDaGxvcm9waHlsbA0KYGBge3J9DQpwYXIobWZyb3c9YygxLDIpKQ0KcGxvdChwcmVzZW5jZSRjaGxfZGVwdGgsIG1haW4gPSAiQ2hsIGF0IERlcHRoIChWYXJpb3VzKSIsIHlsYWIgPSAiQ2hsIChtbW9sLm0tMykiKQ0KcGxvdChwcmVzZW5jZSRjaGxfc3VyZmFjZSwgbWFpbiA9ICJDaGwgYXQgU3VyZmFjZSIsIHlsYWIgPSAiQ2hsIChtbW9sLm0tMykiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy9jaGxfc2ltcGxlcGxvdC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpPMg0KYGBge3J9DQpwYXIobWZyb3c9YygxLDIpKQ0KcGxvdChwcmVzZW5jZSRvMl9kZXB0aCwgbWFpbiA9ICJEaXNzb2x2ZWQgT3h5Z2VuIGF0IERlcHRoIChWYXJpb3VzKSIsIHlsYWIgPSAiQ2hsIChtbW9sLm0tMykiKQ0KcGxvdChwcmVzZW5jZSRvMl9zdXJmYWNlLCBtYWluID0gIkRpc3NvbHZlZCBPeHlnZW4gYXQgU3VyZmFjZSIsIHlsYWIgPSAiTzIgKG1tb2wubS0zKSIpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL28yX3NpbXBsZXBsb3QucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KbWxwDQpgYGB7cn0NCnBsb3QocHJlc2VuY2UkbWxwX3N1cmZhY2UsIG1haW4gPSAiTWl4ZWQgTGF5ZXIgVGhpY2tuZXNzIiwgeWxhYiA9ICJEZXB0aCAobSkiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy9tbHBfc2ltcGxlcGxvdC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpTU0gNCmBgYHtyfQ0KcGxvdChwcmVzZW5jZSRzc2hfc3VyZmFjZSwgbWFpbiA9ICJTZWEgU3VyZmFjZSBIZWlnaHQiLCB5bGFiID0gIkhlaWdodCAobSkiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy9zc2hfc2ltcGxlcGxvdC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpYWFggU0FNIC0gWU9VIFdBTlQgVE8gVEhJTksgQUJPVVQgRE9JTkcgVEhJUyBCWSBERVBUSCBSQVRIRVIgVEhBTiBBTEwgREVQVEhTKQ0KDQpgYGB7cn0NCnVuaXF1ZV9kZXB0aHMgPC0gdW5pcXVlKHByZXNlbmNlJGRlcHRobGF5ZXJubykNCnVuaXF1ZV9kZXB0aGRvcmRlcmVkIDwtIHNvcnQodW5pcXVlX2RlcHRocykgI2p1c3QgcHV0cyB0aGUgbGlzdCBpbiBvZGVyIHdpdGggbm8gTkENCmxlbmd0aCh1bmlxdWVfZGVwdGhkb3JkZXJlZCkNCmBgYA0Kb3VjaCAtIDM5IGxheWVycy4uLiBhIGpvYiBmb3IgYSBib3hwbG90IHByb2JhYmx5DQoNCmBgYHtyfQ0KDQpgYGANCg0KDQoNCiMgZnJlcXVlbmN5IHBsb3RzIG9mIGVudi4gY29ycg0KDQoNCnRlbXBlcmF0dXJlDQpgYGB7cn0NCmhpc3QocHJlc2VuY2UkdGVtcF9zdXJmYWNlLCBtYWluID0gIlRlbXAgYXQgU3VyZmFjZSIsIHhsYWIgPSAiS2VsdmluIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL3RlbXBlcmF0dXJlX3N1cmZhY2VfaGlzdG9ncmFtLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCmBgYHtyfQ0KaGlzdChwcmVzZW5jZSR0ZW1wX2RlcHQsIG1haW4gPSAiVGVtcCBhdCBEZXB0aCIsIHhsYWIgPSAiS2VsdmluIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL3RlbXBlcmF0dXJlX2RlcHRoX2hpc3RvZ3JhbS5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpjaGwNCmBgYHtyfQ0KaGlzdChwcmVzZW5jZSRjaGxfc3VyZmFjZSwgbWFpbiA9ICJDaGxvcm9waHlsbCBhdCBTdXJmYWNlIiwgeGxhYiA9ICJDaGxvcm9waHlsbCBDb25jZW50cmF0aW9ucyAobW1vbC5tLTMpIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL2NobF9zdXJmYWNlX2hpc3RvZ3JhbS5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpgYGB7cn0NCmhpc3QocHJlc2VuY2UkY2hsX2RlcHRoLCBtYWluID0gIkNobG9yb3BoeWxsIGF0IE9ic2VydmF0aW9uIERlcHRoIiwgeGxhYiA9ICJDaGxvcm9waHlsbCBDb25jZW50cmF0aW9ucyAobW1vbC5tLTMpIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL2NobF9kZXB0aF9oaXN0b2dyYW0ucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0Kc2FsaW5pdHkNCmBgYHtyfQ0KaGlzdChwcmVzZW5jZSRzYWxpbml0eV9zdXJmYWNlLCBtYWluID0gIlNhbGluaXR5IGF0IFN1cmZhY2UiLCB4bGFiID0gIlNhbGluaXR5IFByYWN0aWNhbCBTYWxpbml0eSBVbml0IChQU1UpIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL3NhbF9zdXJmYWNlX2hpc3RvZ3JhbS5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpgYGB7cn0NCmhpc3QocHJlc2VuY2Ukc2FsaW5pdHlfZGVwdGgsIG1haW4gPSAiU2FsaW5pdHkgYXQgT2JzZXJ2YXRpb24gRGVwdGgiLCB4bGFiID0gIlNhbGluaXR5IFByYWN0aWNhbCBTYWxpbml0eSBVbml0IChQU1UpIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL3NhbF9kZXB0aF9oaXN0b2dyYW0ucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0Kb3h5Z2VuDQpgYGB7cn0NCmhpc3QocHJlc2VuY2UkbzJfc3VyZmFjZSwgbWFpbiA9ICJEaXNzb2x2ZWQgT3h5Z2VuIGF0IFN1cmZhY2UiLCB4bGFiID0gIk1vbGUgQ29uY2VudHJhdGlvbiBvZiBEaXNzb2x2ZWQgT3h5Z2VuIGluIFNlYSBXYXRlciAobW1vbC5tLTMpIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL28yX3N1cmZhY2VfaGlzdG9ncmFtLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCmBgYHtyfQ0KaGlzdChwcmVzZW5jZSRvMl9kZXB0aCwgbWFpbiA9ICJEaXNzb2x2ZWQgT3h5Z2VuIGF0IE9ic2VydmF0aW9uIERlcHRoIiwgeGxhYiA9ICJNb2xlIENvbmNlbnRyYXRpb24gb2YgRGlzc29sdmVkIE94eWdlbiBpbiBTZWEgV2F0ZXIgKG1tb2wubS0zKSIpDQpkZXYuY29weShwbmcsICIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy9vMl9kZXB0aF9oaXN0b2dyYW0ucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KTUxQDQpgYGB7cn0NCmhpc3QocHJlc2VuY2UkbWxwLCBtYWluID0gIk1peGVkIExheWVyIFRoaWNrbmVzcyBhdCBPYnNlcnZhdGlvbiIsIHhsYWIgPSAiTWl4ZWQgTGF5ZXIgVGhpY2tuZXNzIChtKSIpDQpkZXYuY29weShwbmcsICIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy9tbHBfc3VyZmFjZV9oaXN0b2dyYW0ucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0Kc3NoDQpgYGB7cn0NCmhpc3QocHJlc2VuY2Ukc3NoLCBtYWluID0gIlNlYSBTdXJmYWNlIEhlaWdodCBhdCBPYnNlcnZhdGlvbiIsIHhsYWIgPSAiU2VhIFN1cmZhY2UgSGVpZ2h0IChtKSIpDQpkZXYuY29weShwbmcsICIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy9zc2hfc3VyZmFjZV9oaXN0b2dyYW0ucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KDQojIyBzaW1wbGUgYm94cGxvdHMgb2YgZW52LiBjb3JyDQoNClNhbWUgYXMgYWJvdmUgYnV0IHdpdGggYm94cGxvdHMgKG1heSBwcm92aWRlIHNvbWUgbW9yZSB1c2VmdWwgaW5mbykNCg0KDQoNCmluZGl2aWR1YWwgcGxvdHMgb2YgZWFjaCB2YXJpYWJsZSANCmBgYHtyfQ0KcGFyKG1mcm93PWMoMSwyKSkNCmJveHBsb3QocHJlc2VuY2UkdGVtcF9kZXB0aCwgbWFpbiA9ICJUZW1wZXJhdHVyZSBhdCBEZXB0aCAoVmFyaW91cykiLCB5bGFiID0gIktlbHZpbiIpDQpib3hwbG90KHByZXNlbmNlJHRlbXBfc3VyZmFjZSwgbWFpbiA9ICJUZW1wZXJhdHVyZSBhdCBTdXJmYWNlIiwgeWxhYiA9ICJLZWx2aW4iKQ0KZGV2LmNvcHkocG5nLCAiLi4vb3V0cHV0L2Vudi9zaW1wbGVfcGxvdHMvdGVtcF9ib3hwbG90LnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpwYXIobWZyb3c9YygxLDIpKQ0KYm94cGxvdChwcmVzZW5jZSRzYWxpbml0eV9kZXB0aCwgbWFpbiA9ICJTYWxpbml0eSBhdCBEZXB0aCAoVmFyaW91cykiLCB5bGFiID0gIlBTVSIpDQpib3hwbG90KHByZXNlbmNlJHNhbGluaXR5X3N1cmZhY2UsIG1haW4gPSAiU2FsaW5pdHkgYXQgU3VyZmFjZSIsIHlsYWIgPSAiUFNVIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL3NhbGluaXR5X2JveHBsb3QucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCnBhcihtZnJvdz1jKDEsMikpDQpib3hwbG90KHByZXNlbmNlJG8yX2RlcHRoLCBtYWluID0gIk8yIGF0IERlcHRoIChWYXJpb3VzKSIsIHlsYWIgPSAibW1vbC5tLTMiKQ0KYm94cGxvdChwcmVzZW5jZSRvMl9zdXJmYWNlLCBtYWluID0gIk8yIGF0IFN1cmZhY2UiLCB5bGFiID0gIm1tb2wubS0zIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL28yX2JveHBsb3QucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCnBhcihtZnJvdz1jKDEsMikpDQpib3hwbG90KHByZXNlbmNlJGNobF9kZXB0aCwgbWFpbiA9ICJDaGxvcnBoeWxsIGF0IERlcHRoIChWYXJpb3VzKSIsIHlsYWIgPSAibW1vbC5tLTMiKQ0KYm94cGxvdChwcmVzZW5jZSRjaGxfc3VyZmFjZSwgbWFpbiA9ICJDaGxvcnBoeWxsIGF0IFN1cmZhY2UiLCB5bGFiID0gIm1tb2wubS0zIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL2NobF9ib3hwbG90LnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpwYXIobWZyb3c9YygxLDIpKQ0KYm94cGxvdChwcmVzZW5jZSRtbHBfc3VyZmFjZSwgbWFpbiA9ICJEZW5zaXR5IE1peGVkIExheWVyIFRoaWNrbmVzcyIsIHlsYWIgPSAibWV0ZXJzIikNCmJveHBsb3QocHJlc2VuY2Ukc3NoX3N1cmZhY2UsIG1haW4gPSAiU2VhIFN1cmZhY2UgSGVpZ2h0IiwgeWxhYiA9ICJtZXRlcnMiKQ0KZGV2LmNvcHkocG5nLCAiLi4vb3V0cHV0L2Vudi9zaW1wbGVfcGxvdHMvbWxwX3NzaF9ib3hwbG90LnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCmBgYHtyfQ0KYm94cGxvdChwcmVzZW5jZSR0ZW1wX2RlcHRoIH4gcHJlc2VuY2UkbW9udGgsIHhsYWIgPSAibW9udGgiLCB5bGFiID0gIlRlbXBlcmF0dXJlIChLZWx2aW4pIiwgbWFpbiA9ICJUZW1wZXJhdHVyZSBhdCBPYnNlcnZhdGlvbiBEZXB0aCBwZXIgTW9udGgiKQ0KZGV2LmNvcHkocG5nLCAiLi4vb3V0cHV0L2Vudi9zaW1wbGVfcGxvdHMvdGVtcGVyYXR1cmVfYm94cGxvdF9kZXB0X21vbnRoLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCmBgYHtyfQ0KYm94cGxvdChwcmVzZW5jZSRjaGxfZGVwdGggfiBwcmVzZW5jZSRtb250aCwgeGxhYiA9ICJtb250aCIsIHlsYWIgPSAiQ2hsb3JvcGh5bGwgQ29uY2VudHJhdGlvbnMgKG1tb2wubS0zKSIsIG1haW4gPSAiQ2hsb3JvcGh5bGwgYXQgT2JzZXJ2YXRpb24gRGVwdGggcGVyIE1vbnRoIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL2NobG9yb3BoeWxsX2JveHBsb3RfZGVwdF9tb250aC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpgYGB7cn0NCmJveHBsb3QocHJlc2VuY2Ukc2FsaW5pdHlfZGVwdGggfiBwcmVzZW5jZSRtb250aCwgeGxhYiA9ICJtb250aCIsIHlsYWIgPSAiU2FsaW5pdHkgUHJhY3RpY2FsIFNhbGluaXR5IFVuaXQgKFBTVSkiLCBtYWluID0gIlNhbGluaXR5IGF0IE9ic2VydmF0aW9uIERlcHRoIHBlciBNb250aCIpDQpkZXYuY29weShwbmcsICIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy9zYWxpbml0eV9ib3hwbG90X2RlcHRfbW9udGgucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KYGBge3J9DQpib3hwbG90KHByZXNlbmNlJG8yX2RlcHRoIH4gcHJlc2VuY2UkbW9udGgsIHhsYWIgPSAibW9udGgiLCB5bGFiID0gIk1vbGUgQ29uY2VudHJhdGlvbiBvZiBEaXNzb2x2ZWQgT3h5Z2VuIGluIFNlYSBXYXRlciAobW1vbC5tLTMpIiwgbWFpbiA9ICJEaXNzb2x2ZWQgT3h5Z2VuIGF0IE9ic2VydmF0aW9uIERlcHRoIHBlciBNb250aCIpDQpkZXYuY29weShwbmcsICIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy9vMl9ib3hwbG90X2RlcHRfbW9udGgucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KYGBge3J9DQpib3hwbG90KHByZXNlbmNlJG1scF9zdXJmYWNlIH4gcHJlc2VuY2UkbW9udGgsIHhsYWIgPSAibW9udGgiLCB5bGFiID0gIk1peGVkIExheWVyIFRoaWNrbmVzcyAobSkiLCBtYWluID0gIk1peGVkIExheWVyIFRoaWNrbmVzcyBhdCBPYnNlcnZhdGlvbiBwZXIgTW9udGgiKQ0KZGV2LmNvcHkocG5nLCAiLi4vb3V0cHV0L2Vudi9zaW1wbGVfcGxvdHMvbWxwX2JveHBsb3RfZGVwdF9tb250aC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpgYGB7cn0NCmJveHBsb3QocHJlc2VuY2Ukc3NoX3N1cmZhY2UgfiBwcmVzZW5jZSRtb250aCwgeGxhYiA9ICJtb250aCIsIHlsYWIgPSAiU2VhIFN1cmZhY2UgSGVpZ2h0IChtKSIsIG1haW4gPSAiU2VhIFN1cmZhY2UgSGVpZ2h0IGF0IE9ic2VydmF0aW9uIHBlciBNb250aCIpDQpkZXYuY29weShwbmcsICIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy9zc2hfYm94cGxvdF9kZXB0X21vbnRoLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCmBgYHtyfQ0KYm94cGxvdChwcmVzZW5jZSR0ZW1wX2RlcHRoIH4gcHJlc2VuY2UkeWVhciwgeGxhYiA9ICJZZWFyIiwgeWxhYiA9ICJUZW1wZXJhdHVyZSAoS2VsdmluKSIsIG1haW4gPSAiVGVtcGVyYXR1cmUgYXQgT2JzZXJ2YXRpb24gRGVwdGggcGVyIFllYXIiKQ0KZGV2LmNvcHkocG5nLCAiLi4vb3V0cHV0L2Vudi9zaW1wbGVfcGxvdHMvdGVtcGVyYXR1cmVfYm94cGxvdF9kZXB0X3llYXIucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KYGBge3J9DQpib3hwbG90KHByZXNlbmNlJGNobF9kZXB0aCB+IHByZXNlbmNlJHllYXIsIHhsYWIgPSAiWWVhciIsIHlsYWIgPSAiQ2hsb3JvcGh5bGwgQ29uY2VudHJhdGlvbnMgKG1tb2wubS0zKSIsIG1haW4gPSAiQ2hsb3JvcGh5bGwgYXQgT2JzZXJ2YXRpb24gRGVwdGggcGVyIFllYXIiKQ0KZGV2LmNvcHkocG5nLCAiLi4vb3V0cHV0L2Vudi9zaW1wbGVfcGxvdHMvY2hsX2JveHBsb3RfZGVwdF95ZWFyLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCmBgYHtyfQ0KYm94cGxvdChwcmVzZW5jZSRzYWxpbml0eV9kZXB0aCB+IHByZXNlbmNlJHllYXIsIHhsYWIgPSAiWWVhciIsIHlsYWIgPSAiU2FsaW5pdHkgUHJhY3RpY2FsIFNhbGluaXR5IFVuaXQgKFBTVSkiLCBtYWluID0gIlNhbGluaXR5IGF0IE9ic2VydmF0aW9uIERlcHRoIHBlciBZZWFyIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL3NhbGluaXR5X2JveHBsb3RfZGVwdF95ZWFyLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCmBgYHtyfQ0KYm94cGxvdChwcmVzZW5jZSRvMl9kZXB0aCB+IHByZXNlbmNlJHllYXIsIHhsYWIgPSAiWWVhciIsIHlsYWIgPSAiTW9sZSBDb25jZW50cmF0aW9uIG9mIERpc3NvbHZlZCBPeHlnZW4gaW4gU2VhIFdhdGVyIChtbW9sLm0tMykiLCBtYWluID0gIkRpc3NvbHZlZCBPeHlnZW4gYXQgT2JzZXJ2YXRpb24gRGVwdGggcGVyIFllYXIiKQ0KZGV2LmNvcHkocG5nLCAiLi4vb3V0cHV0L2Vudi9zaW1wbGVfcGxvdHMvb3h5Z2VuX2JveHBsb3RfZGVwdF95ZWFyLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCmBgYHtyfQ0KYm94cGxvdChwcmVzZW5jZSRtbHAgfiBwcmVzZW5jZSR5ZWFyLCB4bGFiID0gIlllYXIiLCB5bGFiID0gIk1peGVkIExheWVyIFRoaWNrbmVzcyAobSkiLCBtYWluID0gIk1peGVkIExheWVyIFRoaWNrbmVzcyBhdCBPYnNlcnZhdGlvbiBwZXIgWWVhciIpDQpkZXYuY29weShwbmcsICIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy9tbHBfYm94cGxvdF9kZXB0X3llYXIucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KYGBge3J9DQpib3hwbG90KHByZXNlbmNlJHNzaCB+IHByZXNlbmNlJHllYXIsIHhsYWIgPSAiWWVhciIsIHlsYWIgPSAiU2VhIFN1cmZhY2UgSGVpZ2h0IChtKSIsIG1haW4gPSAiU2VhIFN1cmZhY2UgSGVpZ2h0IGF0IE9ic2VydmF0aW9uIHBlciBZZWFyIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL3NzaF9ib3hwbG90X2RlcHRfeWVhci5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpgYGB7cn0NCmJveHBsb3QocHJlc2VuY2UkdGVtcF9zdXJmYWNlIH4gcHJlc2VuY2UkbW9udGgsIHhsYWIgPSAibW9udGgiLCB5bGFiID0gIlRlbXBlcmF0dXJlIChLZWx2aW4pIiwgbWFpbiA9ICJUZW1wZXJhdHVyZSBhdCBPYnNlcnZhdGlvbiAoU3VyZmFjZSkgcGVyIE1vbnRoIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL3RlbXBlcmF0dXJlX2JveHBsb3Rfc3VyZmFjZV9tb250aC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpgYGB7cn0NCmJveHBsb3QocHJlc2VuY2UkY2hsX3N1cmZhY2UgfiBwcmVzZW5jZSRtb250aCwgeGxhYiA9ICJtb250aCIsIHlsYWIgPSAiQ2hsb3JvcGh5bGwgQ29uY2VudHJhdGlvbnMgKG1tb2wubS0zKSIsIG1haW4gPSAiQ2hsb3JvcGh5bGwgYXQgT2JzZXJ2YXRpb24gKFN1cmZhY2UpIHBlciBNb250aCIpDQpkZXYuY29weShwbmcsICIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy9jaGxvcm9waHlsbF9ib3hwbG90X3N1cmZhY2VfbW9udGgucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KYGBge3J9DQpib3hwbG90KHByZXNlbmNlJHNhbGluaXR5X3N1cmZhY2UgfiBwcmVzZW5jZSRtb250aCwgeGxhYiA9ICJtb250aCIsIHlsYWIgPSAiU2FsaW5pdHkgUHJhY3RpY2FsIFNhbGluaXR5IFVuaXQgKFBTVSkiLCBtYWluID0gIlNhbGluaXR5IGF0IE9ic2VydmF0aW9uIChTdXJmYWNlKSBwZXIgTW9udGgiKQ0KZGV2LmNvcHkocG5nLCAiLi4vb3V0cHV0L2Vudi9zaW1wbGVfcGxvdHMvc2FsaW5pdHlfYm94cGxvdF9zdXJmYWNlX21vbnRoLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCmBgYHtyfQ0KYm94cGxvdChwcmVzZW5jZSRvMl9zdXJmYWNlIH4gcHJlc2VuY2UkbW9udGgsIHhsYWIgPSAibW9udGgiLCB5bGFiID0gIk1vbGUgQ29uY2VudHJhdGlvbiBvZiBEaXNzb2x2ZWQgT3h5Z2VuIGluIFNlYSBXYXRlciAobW1vbC5tLTMpIiwgbWFpbiA9ICJEaXNzb2x2ZWQgT3h5Z2VuIGF0IE9ic2VydmF0aW9uIChTdXJmYWNlKSBwZXIgTW9udGgiKQ0KZGV2LmNvcHkocG5nLCAiLi4vb3V0cHV0L2Vudi9zaW1wbGVfcGxvdHMvbzJfYm94cGxvdF9zdXJmYWNlX21vbnRoLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCmBgYHtyfQ0KYm94cGxvdChwcmVzZW5jZSRtbHBfc3VyZmFjZSB+IHByZXNlbmNlJG1vbnRoLCB4bGFiID0gIm1vbnRoIiwgeWxhYiA9ICJNaXhlZCBMYXllciBUaGlja25lc3MgKG0pIiwgbWFpbiA9ICJNaXhlZCBMYXllciBUaGlja25lc3MgYXQgT2JzZXJ2YXRpb24gcGVyIE1vbnRoIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL21scF9ib3hwbG90X3N1cmZhY2VfbW9udGgucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KYGBge3J9DQpib3hwbG90KHByZXNlbmNlJHNzaF9zdXJmYWNlIH4gcHJlc2VuY2UkbW9udGgsIHhsYWIgPSAibW9udGgiLCB5bGFiID0gIlNlYSBTdXJmYWNlIEhlaWdodCAobSkiLCBtYWluID0gIlNlYSBTdXJmYWNlIEhlaWdodCBhdCBPYnNlcnZhdGlvbiBwZXIgTW9udGgiKQ0KZGV2LmNvcHkocG5nLCAiLi4vb3V0cHV0L2Vudi9zaW1wbGVfcGxvdHMvc3NoX2JveHBsb3Rfc3VyZmFjZV9tb250aC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpgYGB7cn0NCmJveHBsb3QocHJlc2VuY2UkdGVtcF9zdXJmYWNlIH4gcHJlc2VuY2UkeWVhciwgeGxhYiA9ICJZZWFyIiwgeWxhYiA9ICJUZW1wZXJhdHVyZSAoS2VsdmluKSIsIG1haW4gPSAiVGVtcGVyYXR1cmUgYXQgT2JzZXJ2YXRpb24gKFN1cmZhY2UpIHBlciBZZWFyIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL3RlbXBlcmF0dXJlX2JveHBsb3Rfc3VyZmFjZV95ZWFyLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCmBgYHtyfQ0KYm94cGxvdChwcmVzZW5jZSRjaGxfc3VyZmFjZSB+IHByZXNlbmNlJHllYXIsIHhsYWIgPSAiWWVhciIsIHlsYWIgPSAiQ2hsb3JvcGh5bGwgQ29uY2VudHJhdGlvbnMgKG1tb2wubS0zKSIsIG1haW4gPSAiQ2hsb3JvcGh5bGwgYXQgT2JzZXJ2YXRpb24gKFN1cmZhY2UpIHBlciBZZWFyIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL2NobF9ib3hwbG90X3N1cmZhY2VfeWVhci5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpgYGB7cn0NCmJveHBsb3QocHJlc2VuY2Ukc2FsaW5pdHlfc3VyZmFjZSB+IHByZXNlbmNlJHllYXIsIHhsYWIgPSAiWWVhciIsIHlsYWIgPSAiU2FsaW5pdHkgUHJhY3RpY2FsIFNhbGluaXR5IFVuaXQgKFBTVSkiLCBtYWluID0gIlNhbGluaXR5IGF0IE9ic2VydmF0aW9uIChTdXJmYWNlKSBwZXIgWWVhciIpDQpkZXYuY29weShwbmcsICIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy9zYWxpbml0eV9ib3hwbG90X3N1cmZhY2VfeWVhci5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpgYGB7cn0NCmJveHBsb3QocHJlc2VuY2UkbzJfc3VyZmFjZSB+IHByZXNlbmNlJHllYXIsIHhsYWIgPSAiWWVhciIsIHlsYWIgPSAiTW9sZSBDb25jZW50cmF0aW9uIG9mIERpc3NvbHZlZCBPeHlnZW4gaW4gU2VhIFdhdGVyIChtbW9sLm0tMykiLCBtYWluID0gIkRpc3NvbHZlZCBPeHlnZW4gYXQgT2JzZXJ2YXRpb24gKFN1cmZhY2UpIHBlciBZZWFyIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL294eWdlbl9ib3hwbG90X3N1cmZhY2VfeWVhci5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQoNCiMgYmFja2dyb3VuZCBwb2ludHMNClJlYWQgaW4gdGhlIHByZXNlbmNlIHBvaW50cw0KDQpgYGB7cn0NCmJhY2tncm91bmQgPC0gcmVhZC5jc3YoIi4uL291dHB1dC9iaW8vYmFja2dyb3VuZF9jb21wbGV0ZV9vYnNfY2Vsc19nbG9ib3QuY3N2IiwgaGVhZGVyID0gVFJVRSkNCmhlYWQoYmFja2dyb3VuZCkNCmBgYA0KDQojIGVudmlyb25tZW50YWwgY29ycmVsYXRlcw0KDQoxKSBHZXQgdGhlIG1heCwgbWluLCBhbiBtZWFuIHZhbHVlcyBhbmQgYWRkIGludG8gYSBkYXRhZnJhbWUNCg0KVGVtcGVyYXR1cmUNCmBgYHtyfQ0KdGVtcF9kZXB0aF9tYXhfYmFjayA8LSBtYXgoYmFja2dyb3VuZCR0ZW1wX2RlcHRoLCBuYS5ybSA9IFRSVUUpDQp0ZW1wX2RlcHRoX21pbl9iYWNrIDwtIG1pbihiYWNrZ3JvdW5kJHRlbXBfZGVwdGgsIG5hLnJtID0gVFJVRSkNCnRlbXBfZGVwdGhfbWVhbl9iYWNrIDwtIG1lYW4oYmFja2dyb3VuZCR0ZW1wX2RlcHRoLCBuYS5ybSA9IFRSVUUpDQp0ZW1wX3N1cmZhY2VfbWF4X2JhY2sgPC0gbWF4KGJhY2tncm91bmQkdGVtcF9zdXJmYWNlLCBuYS5ybSA9IFRSVUUpDQp0ZW1wX3N1cmZhY2VfbWluX2JhY2sgPC0gbWluKGJhY2tncm91bmQkdGVtcF9zdXJmYWNlLCBuYS5ybSA9IFRSVUUpDQp0ZW1wX3N1cmZhY2VfbWVhbl9iYWNrIDwtIG1lYW4oYmFja2dyb3VuZCR0ZW1wX3N1cmZhY2UsIG5hLnJtID0gVFJVRSkNCmBgYA0KDQpTYWxpbml0eQ0KYGBge3J9DQpzYWxfZGVwdGhfbWF4X2JhY2sgPC0gbWF4KGJhY2tncm91bmQkc2FsaW5pdHlfZGVwdGgsIG5hLnJtID0gVFJVRSkNCnNhbF9kZXB0aF9taW5fYmFjayA8LSBtaW4oYmFja2dyb3VuZCRzYWxpbml0eV9kZXB0aCwgbmEucm0gPSBUUlVFKQ0Kc2FsX2RlcHRoX21lYW5fYmFjayA8LSBtZWFuKGJhY2tncm91bmQkc2FsaW5pdHlfZGVwdGgsIG5hLnJtID0gVFJVRSkNCnNhbF9zdXJmYWNlX21heF9iYWNrIDwtIG1heChiYWNrZ3JvdW5kJHNhbGluaXR5X3N1cmZhY2UsIG5hLnJtID0gVFJVRSkNCnNhbF9zdXJmYWNlX21pbl9iYWNrIDwtIG1pbihiYWNrZ3JvdW5kJHNhbGluaXR5X3N1cmZhY2UsIG5hLnJtID0gVFJVRSkNCnNhbF9zdXJmYWNlX21lYW5fYmFjayA8LSBtZWFuKGJhY2tncm91bmQkc2FsaW5pdHlfc3VyZmFjZSwgbmEucm0gPSBUUlVFKQ0KYGBgDQoNCkNobA0KYGBge3J9DQpjaGxfZGVwdGhfbWF4X2JhY2sgPC0gbWF4KGJhY2tncm91bmQkY2hsX2RlcHRoLCBuYS5ybSA9IFRSVUUpDQpjaGxfZGVwdGhfbWluX2JhY2sgPC0gbWluKGJhY2tncm91bmQkY2hsX2RlcHRoLCBuYS5ybSA9IFRSVUUpDQpjaGxfZGVwdGhfbWVhbl9iYWNrIDwtIG1lYW4oYmFja2dyb3VuZCRjaGxfZGVwdGgsIG5hLnJtID0gVFJVRSkNCmNobF9zdXJmYWNlX21heF9iYWNrIDwtIG1heChiYWNrZ3JvdW5kJGNobF9zdXJmYWNlLCBuYS5ybSA9IFRSVUUpDQpjaGxfc3VyZmFjZV9taW5fYmFjayA8LSBtaW4oYmFja2dyb3VuZCRjaGxfc3VyZmFjZSwgbmEucm0gPSBUUlVFKQ0KY2hsX3N1cmZhY2VfbWVhbl9iYWNrIDwtIG1lYW4oYmFja2dyb3VuZCRjaGxfc3VyZmFjZSwgbmEucm0gPSBUUlVFKQ0KYGBgDQoNCk8yDQpgYGB7cn0NCm8yX2RlcHRoX21heF9iYWNrIDwtIG1heChiYWNrZ3JvdW5kJG8yX2RlcHRoLCBuYS5ybSA9IFRSVUUpDQpvMl9kZXB0aF9taW5fYmFjayA8LSBtaW4oYmFja2dyb3VuZCRvMl9kZXB0aCwgbmEucm0gPSBUUlVFKQ0KbzJfZGVwdGhfbWVhbl9iYWNrIDwtIG1lYW4oYmFja2dyb3VuZCRvMl9kZXB0aCwgbmEucm0gPSBUUlVFKQ0KbzJfc3VyZmFjZV9tYXhfYmFjayA8LSBtYXgoYmFja2dyb3VuZCRvMl9zdXJmYWNlLCBuYS5ybSA9IFRSVUUpDQpvMl9zdXJmYWNlX21pbl9iYWNrIDwtIG1pbihiYWNrZ3JvdW5kJG8yX3N1cmZhY2UsIG5hLnJtID0gVFJVRSkNCm8yX3N1cmZhY2VfbWVhbl9iYWNrIDwtIG1lYW4oYmFja2dyb3VuZCRvMl9zdXJmYWNlLCBuYS5ybSA9IFRSVUUpDQpgYGANCg0KTUxQDQpgYGB7cn0NCm1scF9zdXJmYWNlX21heF9iYWNrIDwtIG1heChiYWNrZ3JvdW5kJG1scF9zdXJmYWNlLCBuYS5ybSA9IFRSVUUpDQptbHBfc3VyZmFjZV9taW5fYmFjayA8LSBtaW4oYmFja2dyb3VuZCRtbHBfc3VyZmFjZSwgbmEucm0gPSBUUlVFKQ0KbWxwX3N1cmZhY2VfbWVhbl9iYWNrIDwtIG1lYW4oYmFja2dyb3VuZCRtbHBfc3VyZmFjZSwgbmEucm0gPSBUUlVFKQ0KYGBgDQoNClNTSA0KYGBge3J9DQpzc2hfc3VyZmFjZV9tYXhfYmFjayA8LSBtYXgoYmFja2dyb3VuZCRzc2hfc3VyZmFjZSwgbmEucm0gPSBUUlVFKQ0Kc3NoX3N1cmZhY2VfbWluX2JhY2sgPC0gbWluKGJhY2tncm91bmQkc3NoX3N1cmZhY2UsIG5hLnJtID0gVFJVRSkNCnNzaF9zdXJmYWNlX21lYW5fYmFjayA8LSBtZWFuKGJhY2tncm91bmQkc3NoX3N1cmZhY2UsIG5hLnJtID0gVFJVRSkNCmBgYA0KDQpjcmVhdGUgbWF0cml4DQpgYGB7cn0NCnRkYiA8LSBjKHRlbXBfZGVwdGhfbWF4X2JhY2ssIHRlbXBfZGVwdGhfbWluX2JhY2ssIHRlbXBfZGVwdGhfbWVhbl9iYWNrKQ0KdHNiIDwtIGModGVtcF9zdXJmYWNlX21heF9iYWNrLCB0ZW1wX3N1cmZhY2VfbWluX2JhY2ssIHRlbXBfc3VyZmFjZV9tZWFuX2JhY2spDQpzZGIgPC0gYyhzYWxfZGVwdGhfbWF4X2JhY2ssIHNhbF9kZXB0aF9taW5fYmFjaywgc2FsX2RlcHRoX21lYW5fYmFjaykNCnNzYiA8LSBjKHNhbF9zdXJmYWNlX21heF9iYWNrLCBzYWxfc3VyZmFjZV9taW5fYmFjaywgc2FsX3N1cmZhY2VfbWVhbl9iYWNrKQ0KY2RiIDwtIGMoc2FsX2RlcHRoX21heF9iYWNrLCBzYWxfZGVwdGhfbWluX2JhY2ssIHNhbF9kZXB0aF9tZWFuX2JhY2spDQpjc2IgPC0gYyhzYWxfc3VyZmFjZV9tYXhfYmFjaywgc2FsX3N1cmZhY2VfbWluX2JhY2ssIHNhbF9zdXJmYWNlX21lYW5fYmFjaykNCm9kYiA8LSBjKG8yX2RlcHRoX21heF9iYWNrLCBvMl9kZXB0aF9taW5fYmFjaywgbzJfZGVwdGhfbWVhbl9iYWNrKQ0Kb3NiIDwtIGMobzJfc3VyZmFjZV9tYXhfYmFjaywgbzJfc3VyZmFjZV9taW5fYmFjaywgbzJfc3VyZmFjZV9tZWFuX2JhY2spDQptbHBiIDwtIGMobWxwX3N1cmZhY2VfbWF4X2JhY2ssIG1scF9zdXJmYWNlX21pbl9iYWNrLCBtbHBfc3VyZmFjZV9tZWFuX2JhY2spDQpzc2hiIDwtIGMoc3NoX3N1cmZhY2VfbWF4X2JhY2ssIHNzaF9zdXJmYWNlX21pbl9iYWNrLCBzc2hfc3VyZmFjZV9tZWFuX2JhY2spDQplbnZfc3RhdHNfYmFjayA8LSByYmluZCh0ZGIsIHRzYiwgc2RiLCBzc2IsIGNkYiwgY3NiLCBvZGIsIG9zYiwgbWxwYiwgc3NoYikNCnJvdy5uYW1lcyhlbnZfc3RhdHNfYmFjaykgPC0gYygiVGVtcCBEZXB0aCIsICJUZW1wIFN1cmZhY2UiLCAiU2FsaW5pdHkgRGVwdGgiLCAiU2FsaW5pdHkgU3VyZmFjZSIsICJDaGwgRGVwdGgiLCAiQ2hsIFN1cmZhY2UiLCAiT3h5Z2VuIERlcHRoIiwgIk94eWdlbiBTdXJmYWNlIiwgIk1MUCIsICJTU0giKSANCmNvbG5hbWVzKGVudl9zdGF0c19iYWNrKSA8LSBjKCJNYXgiLCAiTWluIiwgIk1lYW4iKQ0Kd3JpdGUuY3N2KGVudl9zdGF0c19iYWNrLCAiLi4vb3V0cHV0L2Vudi9lbnZfY29ycmVsYXRlc19iYWNrZ3JvdW5kX2Jhc2ljX3N0YXRzLmNzdiIsIHJvdy5uYW1lcyA9IFRSVUUpDQplbnZfc3RhdHNfYmFjaw0KYGBgDQoNCnRlbXBlcmF0dXJlDQpgYGB7cn0NCnBhcihtZnJvdz1jKDEsMikpDQpwbG90KGJhY2tncm91bmQkdGVtcF9kZXB0aCwgbWFpbiA9ICJCYWNrZ3JvdW5kIFBvaW50cyBUZW1wIGF0IERlcHRoIChWYXJpb3VzKSIsIHlsYWIgPSAiS2VsdmluIikNCnBsb3QoYmFja2dyb3VuZCR0ZW1wX3N1cmZhY2UsIG1haW4gPSAiQmFja2dyb3VuZCBQb2ludHMgVGVtcCBhdCBTdXJmYWNlIiwgeWxhYiA9ICJLZWx2aW4iKQ0KZGV2LmNvcHkocG5nLCAiLi4vb3V0cHV0L2Vudi9zaW1wbGVfcGxvdHMvdGVtcGVyYXR1cmVfYmFja2dyb3VuZF9zaW1wbGVwbG90LnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCg0Kc2FsaW5pdHkNCmBgYHtyfQ0KcGFyKG1mcm93PWMoMSwyKSkNCnBsb3QoYmFja2dyb3VuZCRzYWxpbml0eV9kZXB0aCwgbWFpbiA9ICJCYWNrZ3JvdW5kIFBvaW50cyBTYWxpbml0eSBhdCBEZXB0aCAoVmFyaW91cykiLCB5bGFiID0gIlByYWN0aWNhbCBTYWxpbml0eSBVbml0cyIpDQpwbG90KGJhY2tncm91bmQkc2FsaW5pdHlfc3VyZmFjZSwgbWFpbiA9ICJCYWNrZ3JvdW5kIFBvaW50cyBTYWxpbml0eSBhdCBTdXJmYWNlIiwgeWxhYiA9ICJQcmFjdGljYWwgU2FsaW5pdHkgVW5pdHMiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy9zYWxpbml0eV9iYWNrZ3JvdW5kX3NpbXBsZXBsb3QucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KQ2hsb3JvcGh5bGwNCmBgYHtyfQ0KcGFyKG1mcm93PWMoMSwyKSkNCnBsb3QoYmFja2dyb3VuZCRjaGxfZGVwdGgsIG1haW4gPSAiQmFja2dyb3VuZCBQb2ludHMgQ2hsIGF0IERlcHRoIChWYXJpb3VzKSIsIHlsYWIgPSAiQ2hsIChtbW9sLm0tMykiKQ0KcGxvdChiYWNrZ3JvdW5kJGNobF9zdXJmYWNlLCBtYWluID0gIkJhY2tncm91bmQgUG9pbnRzIENobCBhdCBTdXJmYWNlIiwgeWxhYiA9ICJDaGwgKG1tb2wubS0zKSIpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL2NobF9iYWNrZ3JvdW5kX3NpbXBsZXBsb3QucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KTzINCmBgYHtyfQ0KcGFyKG1mcm93PWMoMSwyKSkNCnBsb3QoYmFja2dyb3VuZCRvMl9kZXB0aCwgbWFpbiA9ICJCYWNrZ3JvdW5kIFBvaW50cyBEaXNzb2x2ZWQgT3h5Z2VuIGF0IERlcHRoIChWYXJpb3VzKSIsIHlsYWIgPSAiQ2hsIChtbW9sLm0tMykiKQ0KcGxvdChiYWNrZ3JvdW5kJG8yX3N1cmZhY2UsIG1haW4gPSAiQmFja2dyb3VuZCBQb2ludHMgRGlzc29sdmVkIE94eWdlbiBhdCBTdXJmYWNlIiwgeWxhYiA9ICJPMiAobW1vbC5tLTMpIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9zaW1wbGVfcGxvdHMvbzJfYmFja2dyb3VuZF9zaW1wbGVwbG90LnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCm1scA0KYGBge3J9DQpwbG90KGJhY2tncm91bmQkbWxwX3N1cmZhY2UsIG1haW4gPSAiQmFja2dyb3VuZCBQb2ludHMgTWl4ZWQgTGF5ZXIgVGhpY2tuZXNzIiwgeWxhYiA9ICJEZXB0aCAobSkiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy9tbHBfYmFja2dyb3VuZF9zaW1wbGVwbG90LnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNClNTSA0KYGBge3J9DQpwbG90KGJhY2tncm91bmQkc3NoX3N1cmZhY2UsIG1haW4gPSAiQmFja2dyb3VuZCBQb2ludHMgU2VhIFN1cmZhY2UgSGVpZ2h0IiwgeWxhYiA9ICJIZWlnaHQgKG0pIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9zaW1wbGVfcGxvdHMvc3NoX2JhY2tncm91bmRfc2ltcGxlcGxvdC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQojIyBmcmVxdWVuY3kgcGxvdHMgb2YgZW52LiBjb3JyDQoNCg0KdGVtcGVyYXR1cmUNCmBgYHtyfQ0KaGlzdChiYWNrZ3JvdW5kJHRlbXBfc3VyZmFjZSwgbWFpbiA9ICJCYWNrZ3JvdW5kIFRlbXAgYXQgU3VyZmFjZSIsIHhsYWIgPSAiS2VsdmluIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL3RlbXBlcmF0dXJlX2JhY2tncm91bmRfc3VyZmFjZV9oaXN0b2dyYW0ucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KYGBge3J9DQpoaXN0KGJhY2tncm91bmQkdGVtcF9kZXB0LCBtYWluID0gIkJhY2tncm91bmQgVGVtcCBhdCBEZXB0aCIsIHhsYWIgPSAiS2VsdmluIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL3RlbXBlcmF0dXJlX2JhY2tncm91bmRfZGVwdGhfaGlzdG9ncmFtLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCmNobA0KYGBge3J9DQpoaXN0KGJhY2tncm91bmQkY2hsX3N1cmZhY2UsIG1haW4gPSAiQmFja2dyb3VuZCBDaGxvcm9waHlsbCBhdCBTdXJmYWNlIiwgeGxhYiA9ICJDaGxvcm9waHlsbCBDb25jZW50cmF0aW9ucyAobW1vbC5tLTMpIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL2NobF9iYWNrZ3JvdW5kX3N1cmZhY2VfaGlzdG9ncmFtLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCmBgYHtyfQ0KaGlzdChiYWNrZ3JvdW5kJGNobF9kZXB0aCwgbWFpbiA9ICJCYWNrZ3JvdW5kIENobG9yb3BoeWxsIGF0IE9ic2VydmF0aW9uIERlcHRoIiwgeGxhYiA9ICJDaGxvcm9waHlsbCBDb25jZW50cmF0aW9ucyAobW1vbC5tLTMpIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL2NobF9iYWNrZ3JvdW5kX2RlcHRoX2hpc3RvZ3JhbS5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpzYWxpbml0eQ0KYGBge3J9DQpoaXN0KGJhY2tncm91bmQkc2FsaW5pdHlfc3VyZmFjZSwgbWFpbiA9ICJCYWNrZ3JvdW5kIFNhbGluaXR5IGF0IFN1cmZhY2UiLCB4bGFiID0gIlNhbGluaXR5IFByYWN0aWNhbCBTYWxpbml0eSBVbml0IChQU1UpIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL3NhbF9iYWNrZ3JvdW5kX3N1cmZhY2VfaGlzdG9ncmFtLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCmBgYHtyfQ0KaGlzdChiYWNrZ3JvdW5kJHNhbGluaXR5X2RlcHRoLCBtYWluID0gIkJhY2tncm91bmQgU2FsaW5pdHkgYXQgT2JzZXJ2YXRpb24gRGVwdGgiLCB4bGFiID0gIlNhbGluaXR5IFByYWN0aWNhbCBTYWxpbml0eSBVbml0IChQU1UpIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL3NhbF9iYWNrZ3JvdW5kX2RlcHRoX2hpc3RvZ3JhbS5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpveHlnZW4NCmBgYHtyfQ0KaGlzdChiYWNrZ3JvdW5kJG8yX3N1cmZhY2UsIG1haW4gPSAiQmFja2dyb3VuZCBEaXNzb2x2ZWQgT3h5Z2VuIGF0IFN1cmZhY2UiLCB4bGFiID0gIk1vbGUgQ29uY2VudHJhdGlvbiBvZiBEaXNzb2x2ZWQgT3h5Z2VuIGluIFNlYSBXYXRlciAobW1vbC5tLTMpIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL28yX2JhY2tncm91bmRfc3VyZmFjZV9oaXN0b2dyYW0ucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KYGBge3J9DQpoaXN0KGJhY2tncm91bmQkbzJfZGVwdGgsIG1haW4gPSAiQmFja2dyb3VuZCBEaXNzb2x2ZWQgT3h5Z2VuIGF0IE9ic2VydmF0aW9uIERlcHRoIiwgeGxhYiA9ICJNb2xlIENvbmNlbnRyYXRpb24gb2YgRGlzc29sdmVkIE94eWdlbiBpbiBTZWEgV2F0ZXIgKG1tb2wubS0zKSIpDQpkZXYuY29weShwbmcsICIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy9vMl9iYWNrZ3JvdW5kX2RlcHRoX2hpc3RvZ3JhbS5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpNTFANCmBgYHtyfQ0KaGlzdChiYWNrZ3JvdW5kJG1scCwgbWFpbiA9ICJCYWNrZ3JvdW5kIE1peGVkIExheWVyIFRoaWNrbmVzcyBhdCBPYnNlcnZhdGlvbiIsIHhsYWIgPSAiTWl4ZWQgTGF5ZXIgVGhpY2tuZXNzIChtKSIpDQpkZXYuY29weShwbmcsICIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy9tbHBfYmFja2dyb3VuZF9zdXJmYWNlX2hpc3RvZ3JhbS5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpzc2gNCmBgYHtyfQ0KaGlzdChiYWNrZ3JvdW5kJHNzaCwgbWFpbiA9ICJCYWNrZ3JvdW5kIFNlYSBTdXJmYWNlIEhlaWdodCBhdCBPYnNlcnZhdGlvbiIsIHhsYWIgPSAiU2VhIFN1cmZhY2UgSGVpZ2h0IChtKSIpDQpkZXYuY29weShwbmcsICIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy9zc2hfYmFja2dyb3VuZF9zdXJmYWNlX2hpc3RvZ3JhbS5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQojIyBzaW1wbGUgYm94cGxvdHMgb2YgZW52LiBjb3JyDQoNClNhbWUgYXMgYWJvdmUgYnV0IHdpdGggYm94cGxvdHMgKG1heSBwcm92aWRlIHNvbWUgbW9yZSB1c2VmdWwgaW5mbykNCg0KdGVtcGVyYXR1cmUNCg0KDQpgYGB7cn0NCmJveHBsb3QoYmFja2dyb3VuZCR0ZW1wX2RlcHRoIH4gYmFja2dyb3VuZCRtb250aCwgeGxhYiA9ICJtb250aCIsIHlsYWIgPSAiVGVtcGVyYXR1cmUgKEtlbHZpbikiLCBtYWluID0gIlRlbXBlcmF0dXJlIGF0IEJhY2tncm91bmQgRGVwdGggcGVyIE1vbnRoIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL3RlbXBlcmF0dXJlX2JhY2tncm91bmRfYm94cGxvdF9kZXB0X21vbnRoLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCmBgYHtyfQ0KYm94cGxvdChiYWNrZ3JvdW5kJGNobF9kZXB0aCB+IGJhY2tncm91bmQkbW9udGgsIHhsYWIgPSAibW9udGgiLCB5bGFiID0gIkNobG9yb3BoeWxsIENvbmNlbnRyYXRpb25zIChtbW9sLm0tMykiLCBtYWluID0gIkNobG9yb3BoeWxsIGF0IEJhY2tncm91bmQgRGVwdGggcGVyIE1vbnRoIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL2NobG9yb3BoeWxsX2JhY2tncm91bmRfYm94cGxvdF9kZXB0X21vbnRoLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCmBgYHtyfQ0KYm94cGxvdChiYWNrZ3JvdW5kJHNhbGluaXR5X2RlcHRoIH4gYmFja2dyb3VuZCRtb250aCwgeGxhYiA9ICJtb250aCIsIHlsYWIgPSAiU2FsaW5pdHkgUHJhY3RpY2FsIFNhbGluaXR5IFVuaXQgKFBTVSkiLCBtYWluID0gIlNhbGluaXR5IGF0IEJhY2tncm91bmQgRGVwdGggcGVyIE1vbnRoIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL3NhbGluaXR5X2JhY2tncm91bmRfYm94cGxvdF9kZXB0X21vbnRoLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCmBgYHtyfQ0KYm94cGxvdChiYWNrZ3JvdW5kJG8yX2RlcHRoIH4gYmFja2dyb3VuZCRtb250aCwgeGxhYiA9ICJtb250aCIsIHlsYWIgPSAiTW9sZSBDb25jZW50cmF0aW9uIG9mIERpc3NvbHZlZCBPeHlnZW4gaW4gU2VhIFdhdGVyIChtbW9sLm0tMykiLCBtYWluID0gIkRpc3NvbHZlZCBPeHlnZW4gYXQgQmFja2dyb3VuZCBEZXB0aCBwZXIgTW9udGgiKQ0KZGV2LmNvcHkocG5nLCAiLi4vb3V0cHV0L2Vudi9zaW1wbGVfcGxvdHMvbzJfYmFja2dyb3VuZF9ib3hwbG90X2RlcHRfbW9udGgucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KYGBge3J9DQpib3hwbG90KGJhY2tncm91bmQkbWxwX3N1cmZhY2UgfiBiYWNrZ3JvdW5kJG1vbnRoLCB4bGFiID0gIm1vbnRoIiwgeWxhYiA9ICJNaXhlZCBMYXllciBUaGlja25lc3MgKG0pIiwgbWFpbiA9ICJNaXhlZCBMYXllciBUaGlja25lc3MgYXQgQmFja2dyb3VuZCBwZXIgTW9udGgiKQ0KZGV2LmNvcHkocG5nLCAiLi4vb3V0cHV0L2Vudi9zaW1wbGVfcGxvdHMvbWxwX2JhY2tncm91bmRfYm94cGxvdF9kZXB0X21vbnRoLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCmBgYHtyfQ0KYm94cGxvdChiYWNrZ3JvdW5kJHNzaF9zdXJmYWNlIH4gYmFja2dyb3VuZCRtb250aCwgeGxhYiA9ICJtb250aCIsIHlsYWIgPSAiU2VhIFN1cmZhY2UgSGVpZ2h0IChtKSIsIG1haW4gPSAiU2VhIFN1cmZhY2UgSGVpZ2h0IGF0IEJhY2tncm91bmQgcGVyIE1vbnRoIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL3NzaF9iYWNrZ3JvdW5kX2JveHBsb3RfZGVwdF9tb250aC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpgYGB7cn0NCmJveHBsb3QoYmFja2dyb3VuZCR0ZW1wX2RlcHRoIH4gYmFja2dyb3VuZCR5ZWFyLCB4bGFiID0gIlllYXIiLCB5bGFiID0gIlRlbXBlcmF0dXJlIChLZWx2aW4pIiwgbWFpbiA9ICJUZW1wZXJhdHVyZSBhdCBCYWNrZ3JvdW5kIERlcHRoIHBlciBZZWFyIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL3RlbXBlcmF0dXJlX2JhY2tncm91bmRfYm94cGxvdF9kZXB0X3llYXIucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KYGBge3J9DQpib3hwbG90KGJhY2tncm91bmQkY2hsX2RlcHRoIH4gYmFja2dyb3VuZCR5ZWFyLCB4bGFiID0gIlllYXIiLCB5bGFiID0gIkNobG9yb3BoeWxsIENvbmNlbnRyYXRpb25zIChtbW9sLm0tMykiLCBtYWluID0gIkNobG9yb3BoeWxsIGF0IEJhY2tncm91bmQgRGVwdGggcGVyIFllYXIiKQ0KZGV2LmNvcHkocG5nLCAiLi4vb3V0cHV0L2Vudi9zaW1wbGVfcGxvdHMvY2hsX2JhY2tncm91bmRfYm94cGxvdF9kZXB0X3llYXIucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KYGBge3J9DQpib3hwbG90KGJhY2tncm91bmQkc2FsaW5pdHlfZGVwdGggfiBiYWNrZ3JvdW5kJHllYXIsIHhsYWIgPSAiWWVhciIsIHlsYWIgPSAiU2FsaW5pdHkgUHJhY3RpY2FsIFNhbGluaXR5IFVuaXQgKFBTVSkiLCBtYWluID0gIlNhbGluaXR5IGF0IEJhY2tncm91bmQgRGVwdGggcGVyIFllYXIiKQ0KZGV2LmNvcHkocG5nLCAiLi4vb3V0cHV0L2Vudi9zaW1wbGVfcGxvdHMvc2FsaW5pdHlfYmFja2dyb3VuZF9ib3hwbG90X2RlcHRfeWVhci5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpgYGB7cn0NCmJveHBsb3QoYmFja2dyb3VuZCRvMl9kZXB0aCB+IGJhY2tncm91bmQkeWVhciwgeGxhYiA9ICJZZWFyIiwgeWxhYiA9ICJNb2xlIENvbmNlbnRyYXRpb24gb2YgRGlzc29sdmVkIE94eWdlbiBpbiBTZWEgV2F0ZXIgKG1tb2wubS0zKSIsIG1haW4gPSAiRGlzc29sdmVkIE94eWdlbiBhdCBCYWNrZ3JvdW5kIERlcHRoIHBlciBZZWFyIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL294eWdlbl9iYWNrZ3JvdW5kX2JveHBsb3RfZGVwdF95ZWFyLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCmBgYHtyfQ0KYm94cGxvdChiYWNrZ3JvdW5kJG1scCB+IGJhY2tncm91bmQkeWVhciwgeGxhYiA9ICJZZWFyIiwgeWxhYiA9ICJNaXhlZCBMYXllciBUaGlja25lc3MgKG0pIiwgbWFpbiA9ICJNaXhlZCBMYXllciBUaGlja25lc3MgYXQgQmFja2dyb3VuZCBwZXIgWWVhciIpDQpkZXYuY29weShwbmcsICIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy9tbHBfYmFja2dyb3VuZF9ib3hwbG90X2RlcHRfeWVhci5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpgYGB7cn0NCmJveHBsb3QoYmFja2dyb3VuZCRzc2ggfiBiYWNrZ3JvdW5kJHllYXIsIHhsYWIgPSAiWWVhciIsIHlsYWIgPSAiU2VhIFN1cmZhY2UgSGVpZ2h0IChtKSIsIG1haW4gPSAiU2VhIFN1cmZhY2UgSGVpZ2h0IGF0IEJhY2tncm91bmQgcGVyIFllYXIiKQ0KZGV2LmNvcHkocG5nLCAiLi4vb3V0cHV0L2Vudi9zaW1wbGVfcGxvdHMvc3NoX2JhY2tncm91bmRfYm94cGxvdF9kZXB0X3llYXIucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KYGBge3J9DQpib3hwbG90KGJhY2tncm91bmQkdGVtcF9zdXJmYWNlIH4gYmFja2dyb3VuZCRtb250aCwgeGxhYiA9ICJtb250aCIsIHlsYWIgPSAiVGVtcGVyYXR1cmUgKEtlbHZpbikiLCBtYWluID0gIlRlbXBlcmF0dXJlIGF0IEJhY2tncm91bmQgKFN1cmZhY2UpIHBlciBNb250aCIpDQpkZXYuY29weShwbmcsICIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy90ZW1wZXJhdHVyZV9iYWNrZ3JvdW5kX2JveHBsb3Rfc3VyZmFjZV9tb250aC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpgYGB7cn0NCmJveHBsb3QoYmFja2dyb3VuZCRjaGxfc3VyZmFjZSB+IGJhY2tncm91bmQkbW9udGgsIHhsYWIgPSAibW9udGgiLCB5bGFiID0gIkNobG9yb3BoeWxsIENvbmNlbnRyYXRpb25zIChtbW9sLm0tMykiLCBtYWluID0gIkNobG9yb3BoeWxsIGF0IEJhY2tncm91bmQgKFN1cmZhY2UpIHBlciBNb250aCIpDQpkZXYuY29weShwbmcsICIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy9jaGxvcm9waHlsbF9iYWNrZ3JvdW5kX2JveHBsb3Rfc3VyZmFjZV9tb250aC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpgYGB7cn0NCmJveHBsb3QoYmFja2dyb3VuZCRzYWxpbml0eV9zdXJmYWNlIH4gYmFja2dyb3VuZCRtb250aCwgeGxhYiA9ICJtb250aCIsIHlsYWIgPSAiU2FsaW5pdHkgUHJhY3RpY2FsIFNhbGluaXR5IFVuaXQgKFBTVSkiLCBtYWluID0gIlNhbGluaXR5IGF0IEJhY2tncm91bmQgKFN1cmZhY2UpIHBlciBNb250aCIpDQpkZXYuY29weShwbmcsICIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy9zYWxpbml0eV9iYWNrZ3JvdW5kX2JveHBsb3Rfc3VyZmFjZV9tb250aC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpgYGB7cn0NCmJveHBsb3QoYmFja2dyb3VuZCRvMl9zdXJmYWNlIH4gYmFja2dyb3VuZCRtb250aCwgeGxhYiA9ICJtb250aCIsIHlsYWIgPSAiTW9sZSBDb25jZW50cmF0aW9uIG9mIERpc3NvbHZlZCBPeHlnZW4gaW4gU2VhIFdhdGVyIChtbW9sLm0tMykiLCBtYWluID0gIkRpc3NvbHZlZCBPeHlnZW4gYXQgQmFja2dyb3VuZCAoU3VyZmFjZSkgcGVyIE1vbnRoIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL28yX2JhY2tncm91bmRfYm94cGxvdF9zdXJmYWNlX21vbnRoLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCmBgYHtyfQ0KYm94cGxvdChiYWNrZ3JvdW5kJG1scF9zdXJmYWNlIH4gYmFja2dyb3VuZCRtb250aCwgeGxhYiA9ICJtb250aCIsIHlsYWIgPSAiTWl4ZWQgTGF5ZXIgVGhpY2tuZXNzIChtKSIsIG1haW4gPSAiTWl4ZWQgTGF5ZXIgVGhpY2tuZXNzIGF0IEJhY2tncm91bmQgcGVyIE1vbnRoIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL21scF9iYWNrZ3JvdW5kX2JveHBsb3Rfc3VyZmFjZV9tb250aC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpgYGB7cn0NCmJveHBsb3QoYmFja2dyb3VuZCRzc2hfc3VyZmFjZSB+IGJhY2tncm91bmQkbW9udGgsIHhsYWIgPSAibW9udGgiLCB5bGFiID0gIlNlYSBTdXJmYWNlIEhlaWdodCAobSkiLCBtYWluID0gIlNlYSBTdXJmYWNlIEhlaWdodCBhdCBCYWNrZ3JvdW5kIHBlciBNb250aCIpDQpkZXYuY29weShwbmcsICIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy9zc2hfYmFja2dyb3VuZF9ib3hwbG90X3N1cmZhY2VfbW9udGgucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KYGBge3J9DQpib3hwbG90KGJhY2tncm91bmQkdGVtcF9zdXJmYWNlIH4gYmFja2dyb3VuZCR5ZWFyLCB4bGFiID0gIlllYXIiLCB5bGFiID0gIlRlbXBlcmF0dXJlIChLZWx2aW4pIiwgbWFpbiA9ICJUZW1wZXJhdHVyZSBhdCBCYWNrZ3JvdW5kIChTdXJmYWNlKSBwZXIgWWVhciIpDQpkZXYuY29weShwbmcsICIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy90ZW1wZXJhdHVyZV9iYWNrZ3JvdW5kX2JveHBsb3Rfc3VyZmFjZV95ZWFyLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCmBgYHtyfQ0KYm94cGxvdChiYWNrZ3JvdW5kJGNobF9zdXJmYWNlIH4gYmFja2dyb3VuZCR5ZWFyLCB4bGFiID0gIlllYXIiLCB5bGFiID0gIkNobG9yb3BoeWxsIENvbmNlbnRyYXRpb25zIChtbW9sLm0tMykiLCBtYWluID0gIkNobG9yb3BoeWxsIGF0IEJhY2tncm91bmQgKFN1cmZhY2UpIHBlciBZZWFyIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL2NobF9iYWNrZ3JvdW5kX2JveHBsb3Rfc3VyZmFjZV95ZWFyLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCmBgYHtyfQ0KYm94cGxvdChiYWNrZ3JvdW5kJHNhbGluaXR5X3N1cmZhY2UgfiBiYWNrZ3JvdW5kJHllYXIsIHhsYWIgPSAiWWVhciIsIHlsYWIgPSAiU2FsaW5pdHkgUHJhY3RpY2FsIFNhbGluaXR5IFVuaXQgKFBTVSkiLCBtYWluID0gIlNhbGluaXR5IGF0IEJhY2tncm91bmQgKFN1cmZhY2UpIHBlciBZZWFyIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL3NhbGluaXR5X2JhY2tncm91bmRfYm94cGxvdF9zdXJmYWNlX3llYXIucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KYGBge3J9DQpib3hwbG90KGJhY2tncm91bmQkbzJfc3VyZmFjZSB+IGJhY2tncm91bmQkeWVhciwgeGxhYiA9ICJZZWFyIiwgeWxhYiA9ICJNb2xlIENvbmNlbnRyYXRpb24gb2YgRGlzc29sdmVkIE94eWdlbiBpbiBTZWEgV2F0ZXIgKG1tb2wubS0zKSIsIG1haW4gPSAiRGlzc29sdmVkIE94eWdlbiBhdCBCYWNrZ3JvdW5kIChTdXJmYWNlKSBwZXIgWWVhciIpDQpkZXYuY29weShwbmcsICIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy9veHlnZW5fYmFja2dyb3VuZF9ib3hwbG90X3N1cmZhY2VfeWVhci5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQojIyBjb3JyZWxhdGlvbnMgYmV0d2VlbiBiYWNrZ3JvdW5kIHBvaW50cw0KDQpjaGVjayB0byBzZWUgaWYgdGhlcmUgYXJlIGFueSBjb3JyZWxhdGlvbnMgaW4gdGhlIGVudi4gdmFyaWFibGVzIGZvciB0aGUgYmFja2dyb3VuZCBwb2ludHMNCg0KDQpmaXJzdCBzdWJzZXQgdGhlIGVudi5jb3JyZWxhdGUgY29sdW1ucyAoeW91IGRvbid0IG5lZWQgZXZlcnl0aGluZykNCg0KYGBge3J9DQpiYWNrZ3JvdW5kX2VudiA8LSBzdWJzZXQoYmFja2dyb3VuZCwgc2VsZWN0ID0gYyhhbW9fc2FtcGxlLCBhbW9fd2ludGVyLCBhbW9fcHJldiwgbmFvX3NhbXBsZSwgbmFvX3dpbnRlciwgbmFvX3ByZXYsIGNobF9zdXJmYWNlLCBjaGxfZGVwdGgsIG1scF9zdXJmYWNlLCBzc2hfc3VyZmFjZSwgdGVtcF9zdXJmYWNlLCB0ZW1wX2RlcHRoLCBvMl9zdXJmYWNlLCBvMl9kZXB0aCwgc2FsaW5pdHlfc3VyZmFjZSwgc2FsaW5pdHlfZGVwdGgpKQ0KYmFja2dyb3VuZF9lbnZfY29yIDwtIGNvcihiYWNrZ3JvdW5kX2VudiwgdXNlPSJjb21wbGV0ZS5vYnMiLCBtZXRob2QgPSAic3BlYXJtYW4iKSAjbmVlZCB0byBjcmVhdGUgYSBjb3JyZWxhdGlvbiB1c2luZyBjb3IgdG8gcGxvdC4gY29tcGxldGUub2JzIG1lYW5zIG5hLnJtIGluIHRoaXMgcGFja2FnZS4gI3VzaW5nIHNwZWFybWFucyBhcyBzdWl0YWJsZSBmb3Igbm9uLWxpbmVhciByZWxhdGlvbnNoaXBzDQp3cml0ZS5jc3YoYmFja2dyb3VuZF9lbnZfY29yLCAiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX2Vudl9jb3JyLmNzdiIsIHJvdy5uYW1lcyA9IFRSVUUpDQpiYWNrZ3JvdW5kX2NvcnJwbG90IDwtIGNvcnJwbG90KGJhY2tncm91bmRfZW52X2NvciAsIG1ldGhvZCA9ICJjb2xvciIsIHR5cGUgPSAidXBwZXIiLCBvcmRlciA9ICJhbHBoYWJldCIsIHRsLmNleCA9IDAuOCkgDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL2JhY2tncm91bmRfZW52Y29yci5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQp0byBnZXQgc29tZSBkZW5zaXR5IHBsb3RzIGFsbCBpbiBvbmUgZ3JhcGhpYywgeW91IG5lZWQgdG8gY2hhbmdlIGNodW5rIG91dHB1dCB0byBpbiBjb25zb2xlLCB0aGVuIGdvIHRvIHRoZSBwbG90IHRhYiwgbWFrZSBpdCBmaWxsIHRoZSBzY3JlZW4sIHRoZW4gcnVuIHRoZW4gbWFrZSBiaWdnZXIgdGhlbiBzYXZlIDooIChwcm9iYWJseSBhIGJldHRlciB3YXkgLSB0aGlzIHNlZW1zIHRvIGJlIGFuIGlzc3VlIHdpdGggUlN0dWRpbykNCmBgYHtyfQ0KcGFyKG1mcm93PWMoNCw0KSkNCmZvcihpIGluIDE6MTYpew0KICBwbG90KGRlbnNpdHkoYmFja2dyb3VuZF9lbnZbLGldLCBuYS5ybT1UKSwgbWFpbiA9IG5hbWVzKGJhY2tncm91bmRfZW52KVtpXSkNCn0NCmBgYA0KUFVUIFRIRSBDSFVOSyBPVVRQVVQgQkFDSyBUTyBJTkxJTkUNCg0KDQphZGQgbmFmbyByZWdpb24gYW5kIGdlYXIgdHlwZSBpbnRvIHRoZSBtaXgNCg0KDQpmaXJzdCBzdWJzZXQgdGhlIGVudi5jb3JyZWxhdGUgY29sdW1ucyArIGJvdHRvbV9kZXB0aCAoeW91IGRvbid0IG5lZWQgZXZlcnl0aGluZykNCg0KYGBge3J9DQpiYWNrZ3JvdW5kX2VudmJvdGRlcHRoIDwtIHN1YnNldChiYWNrZ3JvdW5kLCBzZWxlY3QgPSBjKGFtb19zYW1wbGUsIGFtb193aW50ZXIsIGFtb19wcmV2LCBuYW9fc2FtcGxlLCBuYW9fd2ludGVyLCBuYW9fcHJldiwgY2hsX3N1cmZhY2UsIGNobF9kZXB0aCwgbWxwX3N1cmZhY2UsIHNzaF9zdXJmYWNlLCB0ZW1wX3N1cmZhY2UsIHRlbXBfZGVwdGgsIG8yX3N1cmZhY2UsIG8yX2RlcHRoLCBzYWxpbml0eV9zdXJmYWNlLCBzYWxpbml0eV9kZXB0aCwgYm90dG9tX2RlcHRoKSkNCmJhY2tncm91bmRfZW52Ym90ZGVwdGhfY29yIDwtIGNvcihiYWNrZ3JvdW5kX2VudmJvdGRlcHRoLCB1c2U9ImNvbXBsZXRlLm9icyIsIG1ldGhvZCA9ICJzcGVhcm1hbiIpICNuZWVkIHRvIGNyZWF0ZSBhIGNvcnJlbGF0aW9uIHVzaW5nIGNvciB0byBwbG90LiBjb21wbGV0ZS5vYnMgbWVhbnMgbmEucm0gaW4gdGhpcyBwYWNrYWdlLiAjdXNpbmcgc3BlYXJtYW5zIGFzIHN1aXRhYmxlIGZvciBub24tbGluZWFyIHJlbGF0aW9uc2hpcHMNCndyaXRlLmNzdihiYWNrZ3JvdW5kX2VudmJvdGRlcHRoX2NvciwgIi4uL291dHB1dC9lbnYvYmFja2dyb3VuZF9lbnZib3RkZXB0aF9jb3IuY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkNCmJhY2tncm91bmRfY29ycnBsb3QgPC0gY29ycnBsb3QoYmFja2dyb3VuZF9lbnZib3RkZXB0aF9jb3IgLCBtZXRob2QgPSAiY29sb3IiLCB0eXBlID0gInVwcGVyIiwgb3JkZXIgPSAiYWxwaGFiZXQiLCB0bC5jZXggPSAwLjgpIA0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy9iYWNrZ3JvdW5kX2VudmJvdGRlcHRoX2Nvci5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQoNCiMjIGNvcnJlbGF0aW9ucyBiZXR3ZWVuIHByZXNlbmNlIHBvaW50cw0KDQpjaGVjayB0byBzZWUgaWYgdGhlcmUgYXJlIGFueSBjb3JyZWxhdGlvbnMgaW4gdGhlIGVudi4gdmFyaWFibGVzDQoNCmZpcnN0IHN1YnNldCB0aGUgZW52LmNvcnJlbGF0ZSBjb2x1bW5zICh5b3UgZG9uJ3QgbmVlZCBldmVyeXRoaW5nKSB0aGVuIHVzZSBjb3IgdG8gZ2V0IHRoZSBjb3JyZWxhdGlvbiB2YWx1ZXMsIGFuZCB0aGVuIGNvcnJwbG90IGZvciBhIHZpc3VhbA0KDQpgYGB7cn0NCnByZXNfZW52IDwtIHN1YnNldChwcmVzZW5jZSwgc2VsZWN0ID0gYyhhbW9fc2FtcGxlLCBhbW9fd2ludGVyLCBhbW9fcHJldiwgbmFvX3NhbXBsZSwgbmFvX3dpbnRlciwgbmFvX3ByZXYsIGNobF9zdXJmYWNlLCBjaGxfZGVwdGgsIG1scF9zdXJmYWNlLCBzc2hfc3VyZmFjZSwgdGVtcF9zdXJmYWNlLCB0ZW1wX2RlcHRoLCBvMl9zdXJmYWNlLCBvMl9kZXB0aCwgc2FsaW5pdHlfc3VyZmFjZSwgc2FsaW5pdHlfZGVwdGgsIGJvdHRvbV9kZXB0aCkpDQpwcmVzX2Vudl9jb3IgPC0gY29yKHByZXNfZW52LCB1c2U9ImNvbXBsZXRlLm9icyIsIG1ldGhvZCA9ICJzcGVhcm1hbiIpICNuZWVkIHRvIGNyZWF0ZSBhIGNvcnJlbGF0aW9uIHVzaW5nIGNvciB0byBwbG90LiBjb21wbGV0ZS5vYnMgbWVhbnMgbmEucm0gaW4gdGhpcyBwYWNrYWdlLiAjdXNpbmcgc3BlYXJtYW5zIGFzIHN1aXRhYmxlIGZvciBub24tbGluZWFyIHJlbGF0aW9uc2hpcHMNCndyaXRlLmNzdihwcmVzX2Vudl9jb3IsICIuLi9vdXRwdXQvZW52L3ByZXNfZW52X2NvcnIuY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkNCnByZXNfY29ycnBsb3QgPC0gY29ycnBsb3QocHJlc19lbnZfY29yICwgbWV0aG9kID0gImNvbG9yIiwgdHlwZSA9ICJ1cHBlciIsIG9yZGVyID0gImFscGhhYmV0IiwgdGwuY2V4ID0gMC44KSANCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9zaW1wbGVfcGxvdHMvcHJlc19lbnZjb3JyLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCnRvIGdldCBzb21lIGRlbnNpdHkgcGxvdHMgYWxsIGluIG9uZSBncmFwaGljLCB5b3UgbmVlZCB0byBjaGFuZ2UgY2h1bmsgb3V0cHV0IHRvIGluIGNvbnNvbGUsIHRoZW4gZ28gdG8gdGhlIHBsb3QgdGFiLCBtYWtlIGl0IGZpbGwgdGhlIHNjcmVlbiwgdGhlbiBydW4gdGhlbiBtYWtlIGJpZ2dlciB0aGVuIHNhdmUgOiggKHByb2JhYmx5IGEgYmV0dGVyIHdheSAtIHRoaXMgc2VlbXMgdG8gYmUgYW4gaXNzdWUgd2l0aCBSU3R1ZGlvKQ0KYGBge3J9DQpwYXIobWZyb3c9Yyg0LDQpKQ0KZm9yKGkgaW4gMToxNil7DQogIHBsb3QoZGVuc2l0eShwcmVzX2VudlssaV0sIG5hLnJtPVQpLCBtYWluID0gbmFtZXMocHJlc19lbnYpW2ldKQ0KfQ0KYGBgDQpQVVQgVEhFIENIVU5LIE9VVFBVVCBCQUNLIFRPIElOTElORQ0KDQoNCiMjIGRlbnNpdHkgcGxvdCB3aXRoIGJhY2tncm91bmQgYW5kIHByZXNlbmNlIGVudi4gZGF0YQ0KDQpJbnNwaXJlZCBieSBNZXJyb3cgMjAxMyAtIHRvcCBwYXJhZ3JhcGggb2YgcGFnZSAxMDYzIChhcmUgdGhlIHNwZWNpZXMgb2JzZXJ2YXRpb25zIHVuaWZvcm1seSBkaXN0cmlidXRlZCBvdmVyIHRoZSBiYWNrZ3JvdW5kLCBvciBhcmUgdGhleSBza2V3ZWQpDQoNCmBgYHtyfQ0KZ2dwbG90KHByZXNfZW52LCBhZXMoeCA9IHRlbXBfZGVwdGgpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPWJhY2tncm91bmRfZW52LCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9zaW1wbGVfcGxvdHMvdGVtcF9kZXB0aF9iYWNrdnNwcmVzLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KHByZXNfZW52LCBhZXMoeCA9IHRlbXBfc3VyZmFjZSkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9YmFja2dyb3VuZF9lbnYsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy90ZW1wX3N1cmZhY2VfYmFja3ZzcHJlcy5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpgYGB7cn0NCmdncGxvdChwcmVzX2VudiwgYWVzKHggPSBjaGxfc3VyZmFjZSkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9YmFja2dyb3VuZF9lbnYsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy9jaGxfc3VyZmFjZV9iYWNrdnNwcmVzLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KHByZXNfZW52LCBhZXMoeCA9IGNobF9kZXB0aCkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9YmFja2dyb3VuZF9lbnYsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy9jaGxfZGVwdGhfYmFja3ZzcHJlcy5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpgYGB7cn0NCmdncGxvdChwcmVzX2VudiwgYWVzKHggPSBzYWxpbml0eV9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT1iYWNrZ3JvdW5kX2VudiwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL3NhbGluaXR5X3N1cmZhY2VfYmFja3ZzcHJlcy5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpgYGB7cn0NCmdncGxvdChwcmVzX2VudiwgYWVzKHggPSBzYWxpbml0eV9kZXB0aCkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9YmFja2dyb3VuZF9lbnYsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L3NpbXBsZV9wbG90cy9zYWxpbml0eV9kZXB0aF9iYWNrdnNwcmVzLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KHByZXNfZW52LCBhZXMoeCA9IG8yX3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPWJhY2tncm91bmRfZW52LCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9zaW1wbGVfcGxvdHMvbzJfc3VyZmFjZV9iYWNrdnNwcmVzLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KHByZXNfZW52LCBhZXMoeCA9IG8yX2RlcHRoKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT1iYWNrZ3JvdW5kX2VudiwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvc2ltcGxlX3Bsb3RzL28yX2RlcHRoX2JhY2t2c3ByZXMucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QocHJlc19lbnYsIGFlcyh4ID0gbWxwX3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPWJhY2tncm91bmRfZW52LCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9zaW1wbGVfcGxvdHMvbWxwX2JhY2t2c3ByZXMucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QocHJlc19lbnYsIGFlcyh4ID0gc3NoX3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPWJhY2tncm91bmRfZW52LCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9zaW1wbGVfcGxvdHMvc3NoX2JhY2t2c3ByZXMucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KDQojIE5BRk8gUmVnaW9ucw0KDQpjb21wYXJlIHRoZSBlbnZpcm9ubWVudGFsIGNvcnJlbGF0ZXMgYmV0d2VlbiBkaWZmZXJlbnQgTkFGTyByZWdpb25zDQoNCmZpcnN0IHNlZSB3aGljaCBuYWZvIHpvbmVzIHdlcmUgc2FtcGxlZCBpbiBlYWNoIHllYXINCmBgYHtyIHByZXNlbmNlIG5hZm8gYnkgeWVhcn0NCm5hZm9fYnlfeXIgPC0gd2l0aChwcmVzZW5jZSwgdGFibGUoeWVhciwgbmFmb196b25lKSkNCndyaXRlLmNzdihuYWZvX2J5X3lyLCBmaWxlID0gIi4uL291dHB1dC9iaW8vbmFmb3pvbmVfYnlfeXIuY3N2IikNCm5hZm9fYnlfeXINCmBgYA0KDQphbmQgYnkgbW9udGgNCmBgYHtyIHByc2VuY2UgbmFmbyBieSBtb250aH0NCm5hZm9fYnlfbXRoIDwtIHdpdGgocHJlc2VuY2UsIHRhYmxlKG5hZm9fem9uZSwgbW9udGgpKQ0Kd3JpdGUuY3N2KG5hZm9fYnlfbXRoLCBmaWxlID0gIi4uL291dHB1dC9iaW8vbmFmb3pvbmVfYnlfbXRoLmNzdiIpDQpuYWZvX2J5X210aA0KYGBgDQoNCkludGVyZXN0aW5nIHRoYXQgdGhlcmUgaXMgYSBwb2ludCBpbiAxQyAtIHRoaXMgaXMgb3V0c2lkZSBDYW5hZGlhbiB3YXRlcnMuLi4uIGFueXdheQ0KYGBge3J9DQpvbmVjIDwtICBzdWJzZXQocHJlc2VuY2UsIG5hZm9fem9uZSA9PSAiMUMiKQ0Kb25lYw0KYGBgDQoNCiMjIGRlbnNpdHkgcGxvdCB3aXRoIGJhY2tncm91bmQgYW5kIHByZXNlbmNlIGVudi4gZGF0YSBieSBOQUZPIHJlZ2lvbg0KDQpXaGF0IEkgd2FudCB0byBzZWUgaWYgaWYgdGhlcmUgaXMgYSBtYXJrZWQgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBlbnYuIGNvcnJlbGF0ZXMgb2YgdGhlIHByZXNlbmNlIHBvaW50cyBiZXR3ZWVuIE5BRk8gcmVnaW9ucy4gVGhpcyBpcyBhbHNvIHRvIHRyeSBkZWFsIHdpdGggc2FtcGxpbmcgYmlhcyAoYi9jIHRoZSB3aG9sZSByZWdpb24gaXMgbm90IHVuaWZvcm1seSBzYW1wbGVkIGluIGVhY2ggbW9udGgsIGJ1dCByYXRoZXIgbmFmbyByZWdpb25zIGhhdmUgYSBzdHJvbmcgbW9udGggYmlhcykNCg0KZmlyc3QgY3JlYXRlIE5BRk8tcmVnaW9uIGRhdGFzZXRzDQoNCmBgYHtyIHByZXNlbmNlIGJ5IG5hZm99DQpuYWZvMGEgPC0gc3Vic2V0KHByZXNlbmNlLCBuYWZvX3pvbmUgPT0gIjBBIikNCm5hZm8wYiA8LSBzdWJzZXQocHJlc2VuY2UsIG5hZm9fem9uZSA9PSAiMEIiKQ0KbmFmbzFjIDwtIHN1YnNldChwcmVzZW5jZSwgbmFmb196b25lID09ICIxQyIpDQpuYWZvMmcgPC0gc3Vic2V0KHByZXNlbmNlLCBuYWZvX3pvbmUgPT0gIjJHIikNCm5hZm8yaCA8LSBzdWJzZXQocHJlc2VuY2UsIG5hZm9fem9uZSA9PSAiMkgiKQ0KbmFmbzJqIDwtIHN1YnNldChwcmVzZW5jZSwgbmFmb196b25lID09ICIySiIpDQpuYWZvM2sgPC0gc3Vic2V0KHByZXNlbmNlLCBuYWZvX3pvbmUgPT0gIjNLIikNCm5hZm8zbCA8LSBzdWJzZXQocHJlc2VuY2UsIG5hZm9fem9uZSA9PSAiM0wiKQ0KbmFmbzNtIDwtIHN1YnNldChwcmVzZW5jZSwgbmFmb196b25lID09ICIzTSIpDQpuYWZvM24gPC0gc3Vic2V0KHByZXNlbmNlLCBuYWZvX3pvbmUgPT0gIjNOIikNCm5hZm8zbyA8LSBzdWJzZXQocHJlc2VuY2UsIG5hZm9fem9uZSA9PSAiM08iKQ0KbmFmbzNwcyA8LSBzdWJzZXQocHJlc2VuY2UsIG5hZm9fem9uZSA9PSAiM1BzIikNCm5hZm80ciA8LSBzdWJzZXQocHJlc2VuY2UsIG5hZm9fem9uZSA9PSAiNFIiKQ0KbmFmbzRzIDwtIHN1YnNldChwcmVzZW5jZSwgbmFmb196b25lID09ICI0UyIpDQpuYWZvNHQgPC0gc3Vic2V0KHByZXNlbmNlLCBuYWZvX3pvbmUgPT0gIjRUIikNCm5hZm80dm4gPC0gc3Vic2V0KHByZXNlbmNlLCBuYWZvX3pvbmUgPT0gIjRWbiIpDQpuYWZvNHZzIDwtIHN1YnNldChwcmVzZW5jZSwgbmFmb196b25lID09ICI0VnMiKQ0KbmFmbzR3IDwtIHN1YnNldChwcmVzZW5jZSwgbmFmb196b25lID09ICI0VyIpDQpuYWZvNHggPC0gc3Vic2V0KHByZXNlbmNlLCBuYWZvX3pvbmUgPT0gIjRYIikNCm5hZm81eSA8LSBzdWJzZXQocHJlc2VuY2UsIG5hZm9fem9uZSA9PSAiNVkiKQ0KbmFmbzV6ZSA8LSBzdWJzZXQocHJlc2VuY2UsIG5hZm9fem9uZSA9PSAiNVpFIikNCm5hZm9odWRzb24gPC0gc3Vic2V0KHByZXNlbmNlLCBuYWZvX3pvbmUgPT0gIkh1ZHNvblN0cmFpdCIpDQpgYGANCg0KcGxvdCBieSBlYWNoIHZhcmlhYmxlLCBsZXNzIDNtICgyIHNhbXBsZXMpIDFjIChvbmUgc2FtcGxlKSBhbmQgNXplICh6ZXJvIHNhbXBsZXM/ISkNCmBgYHtyIHByZXNlbmNlIGJ5IG5hZm8gYnkgdmFyaWFibGV9DQpnZ3Bsb3QobmFmbzBhLCBhZXMoeCA9IHRlbXBfc3VyZmFjZSwgY29sb3VyID0gbmFmb196b25lKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8wYiwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8yZywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8yaCwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8yaiwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8zaywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8zbCwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8zbiwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8zbywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8zcHMsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNHIsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNHMsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNHQsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNHZuLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzR2cywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm80dywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm80eCwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm81eSwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm9odWRzb24sIG5hLnJtID0gVFJVRSkNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9lbnZfYnlfbmFmb19wbG90cy90ZW1wX3N1cmZhY2VfbmFmby5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KG5hZm8wYSwgYWVzKHggPSB0ZW1wX2RlcHRoLCBjb2xvdXIgPSBuYWZvX3pvbmUpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzBiLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzJnLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzJoLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzJqLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzNrLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzNsLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzNuLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzNvLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzNwcywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm80ciwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm80cywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm80dCwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm80dm4sIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNHZzLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzR3LCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzR4LCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzV5LCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmb2h1ZHNvbiwgbmEucm0gPSBUUlVFKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2Vudl9ieV9uYWZvX3Bsb3RzL3RlbXBfZGVwdGhfbmFmby5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KG5hZm8wYSwgYWVzKHggPSBjaGxfc3VyZmFjZSwgY29sb3VyID0gbmFmb196b25lKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8wYiwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8yZywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8yaCwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8yaiwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8zaywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8zbCwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8zbiwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8zbywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8zcHMsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNHIsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNHMsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNHQsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNHZuLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzR2cywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm80dywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm80eCwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm81eSwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm9odWRzb24sIG5hLnJtID0gVFJVRSkNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9lbnZfYnlfbmFmb19wbG90cy9jaGxfc3VyZmFjZV9uYWZvLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QobmFmbzBhLCBhZXMoeCA9IGNobF9kZXB0aCwgY29sb3VyID0gbmFmb196b25lKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8wYiwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8yZywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8yaCwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8yaiwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8zaywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8zbCwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8zbiwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8zbywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8zcHMsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNHIsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNHMsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNHQsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNHZuLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzR2cywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm80dywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm80eCwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm81eSwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm9odWRzb24sIG5hLnJtID0gVFJVRSkNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9lbnZfYnlfbmFmb19wbG90cy9jaGxfZGVwdGhfbmFmby5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KG5hZm8wYSwgYWVzKHggPSBzYWxpbml0eV9zdXJmYWNlLCBjb2xvdXIgPSBuYWZvX3pvbmUpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzBiLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzJnLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzJoLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzJqLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzNrLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzNsLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzNuLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzNvLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzNwcywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm80ciwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm80cywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm80dCwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm80dm4sIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNHZzLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzR3LCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzR4LCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzV5LCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmb2h1ZHNvbiwgbmEucm0gPSBUUlVFKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2Vudl9ieV9uYWZvX3Bsb3RzL3NhbGluaXR5X3N1cmZhY2VfbmFmby5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KG5hZm8wYSwgYWVzKHggPSBzYWxpbml0eV9kZXB0aCwgY29sb3VyID0gbmFmb196b25lKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8wYiwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8yZywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8yaCwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8yaiwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8zaywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8zbCwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8zbiwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8zbywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm8zcHMsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNHIsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNHMsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNHQsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNHZuLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzR2cywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm80dywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm80eCwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm81eSwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm9odWRzb24sIG5hLnJtID0gVFJVRSkNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9lbnZfYnlfbmFmb19wbG90cy9zYWxpbml0eV9kZXB0aF9uYWZvLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QobmFmbzBhLCBhZXMoeCA9IG8yX3N1cmZhY2UsIGNvbG91ciA9IG5hZm9fem9uZSkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvMGIsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvMmcsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvMmgsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvMmosIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvM2ssIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvM2wsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvM24sIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvM28sIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvM3BzLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzRyLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzRzLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzR0LCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzR2biwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm80dnMsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNHcsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNHgsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNXksIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvaHVkc29uLCBuYS5ybSA9IFRSVUUpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvZW52X2J5X25hZm9fcGxvdHMvbzJfc3VyZmFjZV9uYWZvLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QobmFmbzBhLCBhZXMoeCA9IG8yX2RlcHRoLCBjb2xvdXIgPSBuYWZvX3pvbmUpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzBiLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzJnLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzJoLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzJqLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzNrLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzNsLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzNuLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzNvLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzNwcywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm80ciwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm80cywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm80dCwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm80dm4sIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNHZzLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzR3LCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzR4LCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzV5LCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmb2h1ZHNvbiwgbmEucm0gPSBUUlVFKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2Vudl9ieV9uYWZvX3Bsb3RzL28yX2RlcHRoX25hZm8ucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdChuYWZvMGEsIGFlcyh4ID0gbWxwX3N1cmZhY2UsIGNvbG91ciA9IG5hZm9fem9uZSkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvMGIsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvMmcsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvMmgsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvMmosIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvM2ssIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvM2wsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvM24sIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvM28sIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvM3BzLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzRyLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzRzLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzR0LCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzR2biwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm80dnMsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNHcsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNHgsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNXksIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvaHVkc29uLCBuYS5ybSA9IFRSVUUpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvZW52X2J5X25hZm9fcGxvdHMvbWxwX25hZm8ucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdChuYWZvMGEsIGFlcyh4ID0gc3NoX3N1cmZhY2UsIGNvbG91ciA9IG5hZm9fem9uZSkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvMGIsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvMmcsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvMmgsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvMmosIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvM2ssIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvM2wsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvM24sIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvM28sIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvM3BzLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzRyLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzRzLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzR0LCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9bmFmbzR2biwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPW5hZm80dnMsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNHcsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNHgsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvNXksIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1uYWZvaHVkc29uLCBuYS5ybSA9IFRSVUUpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvZW52X2J5X25hZm9fcGxvdHMvc3NoX25hZm8ucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KDQoNCkxldCdzIHBsb3QgdGhlIHZhcmlhYmxlcyBieSBuYWZvIHJlZ2lvbi95ZWFyIHRoZW4gYnkgbW9udGgNCg0KDQpgYGB7cn0NCnByOTggPC0gc3Vic2V0KHByZXNlbmNlLCB5ZWFyID09ICIxOTk4IikNCmJveHBsb3QocHI5OCR0ZW1wX2RlcHRoIH4gcHI5OCRuYWZvX3pvbmUsIHhsYWIgPSAiTkFGTyBSZWdpb24iLCB5bGFiID0gIlRlbXBlcmF0dXJlIChLZWx2aW4pIiwgbWFpbiA9ICJUZW1wZXJhdHVyZSBhdCBPYnNlcnZhdGlvbiBEZXB0aCBwZXIgTkFGTyBab25lIikNCmBgYA0KDQpgYGB7cn0NCnByOTggPC0gc3Vic2V0KHByZXNlbmNlLCB5ZWFyID09ICIxOTk4IikNCnByMTEgPC0gc3Vic2V0KHByZXNlbmNlLCB5ZWFyID09ICIyMDExIikNCnBhcihtZnJvdz1jKDIsMSkpDQpib3hwbG90KHByOTgkdGVtcF9kZXB0aCB+IHByOTgkbmFmb196b25lLCB4bGFiID0gIk5BRk8gUmVnaW9uIiwgeWxhYiA9ICJUZW1wZXJhdHVyZSAoS2VsdmluKSIsIG1haW4gPSAiVGVtcGVyYXR1cmUgYXQgT2JzZXJ2YXRpb24gRGVwdGggcGVyIE5BRk8gWm9uZSIpDQpib3hwbG90KHByMTEkdGVtcF9kZXB0aCB+IHByMTEkbmFmb196b25lLCB4bGFiID0gIk5BRk8gUmVnaW9uIiwgeWxhYiA9ICJUZW1wZXJhdHVyZSAoS2VsdmluKSIsIG1haW4gPSAiVGVtcGVyYXR1cmUgYXQgT2JzZXJ2YXRpb24gRGVwdGggcGVyIE5BRk8gWm9uZSIpDQpgYGANCg0Kb2sgc2NyYXAgdGhlIG5hZm8gcmVnaW9uIGFuYWx5c2lzIC0gaXQgaXMgdG9vIG1peGVkIHVwIHdpdGggbW9udGggKHNvIHNlZWluZyBpZiByZWdpb24gb3IgbW9udGggaXMgYSBmYWN0b3IgdGhhdCBuZWVkcyB0byBiZSBmYWN0b3JlZCBpbiB0byB0aGUgbW9kZWwgaXMgbm90IGFwcHJvcHJpYXRlKQ0KDQojIHJlbWFwIHdobyBzYW1wbGVkDQoNCk5vdyBsZXRzIGNoZWNrIHRoZSBudW1iZXIgb2YgcmVjb3JkcyBhbmQgc3BhdGlhbC10ZW1wb3JhbCBkaXN0cmlidXRpb24gb2YgdGhlIG9ic2VydmF0aW9ucyBieSBpbnN0aXR1dGlvbiBjb2RlIHRvIG1ha2Ugc3VyZSBub25lIGFyZSBkb2RneQ0KDQpmaXJzdCBhIHRhYmxlIG9mIGhvdyBtYW55IG9ic2VydmF0aW9ucyBlYWNoIGluc3RpdHVpb25jb2RlIGhhcw0KYGBge3IgaW5zdGl0dXRpb24gY29kZSBhbmFseXNpcyAtIGNvdW50fQ0Kb2JzX2J5X2lucyA8LSBjb3VudChwcmVzZW5jZSwgImluc3RpdHV0aW9uY29kZSIpDQpvYnNfYnlfaW5zDQp3cml0ZS5jc3Yob2JzX2J5X2lucywgZmlsZSA9ICIuLi9vdXRwdXQvYmlvL3NhbXBsaW5naW5zdGl0dXRpb25zL25vX29ic2VydmF0aW9uc19pbnN0aXR1dGlvbmNvZGUuY3N2IikNCmBgYA0Kb2sgc28gSU1SLCBOQUZPLCBJQ0VTLCAmIFVTTSBoYXZlIHZlcnkgZmV3IGVudHJpZXMgKDEsIDEsIDEsIGFuZCAzIHJlc3BlY3RpdmVseSkNCg0KTGV0cyB0YWtlIGEgbG9vayBhdCB0aGUgc3BhdGlhbCBicmVha2Rvd24gb2YgdGhlc2UgaW5zdGl0dXRpb25zLkZpcnN0IGFsbCBwb2ludHMuLi4NCg0KYGBge3J9DQptYXAyIDwtIGdldE1hcChyZXNvbHV0aW9uID0gImxvdyIpICNjcmVhdGVzIGFuIG9iamVjdCBjYWxsZWQgbWFwIGF0IGxvdyByZXNvdWx0aW9uDQpwbG90KG1hcDIsIHhsaW0gPSBjKC03MCwgLTQzKSwgeWxpbSA9YygzOCwgNzApLCBhc3AgPSAxLCBtYWluID0gIkFsbCBPY2N1cnJlbmNlcyIsIGNvbCA9ICJjb3Juc2lsayIpICN0aGUgeCBhbmQgeSBsaW0gYXJlIHRoZSBsb25nLWxhdCBib3VuZHMgb2YgdGhlIG1hcA0KcG9pbnRzKHByZXNlbmNlJGRlY2ltYWxMb25naXR1ZGUsIHByZXNlbmNlJGRlY2ltYWxMYXRpdHVkZSwgY29sID0gInJlZCIpICN0aGlzIGFkZHMgcG9pbnRzIHRvIHRoZSBtYXBldCIsIHhsYWIgPSAiTG9uZ2l0dWRlIiwgeWxhYiA9ICJMYXRpdHVkZSIpDQpkZXYuY29weShwbmcsICIuLi9vdXRwdXQvYmlvL3NhbXBsaW5naW5zdGl0dXRpb25zL2FsbF9vY2N1cnJlbmNlcy5wbmciKSAjdGhpcyBwcmludHMgYSBwbmcgb2YgdGhlIHBsb3QNCmRldi5vZmYoKSAjdGhpcyB0dXJucyBvZmYgdGhlIHByaW50IGNvbW1hbmQNCmBgYA0KTm90ZSB0aGVyZSBpcyBvbmUgcG9pbnQgdXAgYnkgaWNlbGFuZCB0aGF0IHlvdSBzaG91bGQgZ2V0IHJpZCBvZiAoSWNlbGFuZGljIHBvcHVsYXRpb24gdGhvdWdodCB0byBiZSBzZXBlcmF0ZSBmcm9tIExhYnJhZG9yLCBidXQgaXQgaXMgdW5jbGVhciBpZiB0aGlzIGlzIHRydWUgb3Igbm90KS4NCg0KTWFwIHRoZSBpbnN0aXR1dGlvbmNvZGUgPT0gQVJDIG9ubHkgZGF0YS4uLg0KYGBge3IgbWFwIG9icyBieSBpbnN0aXR1dHVpb259DQpBUkNfb2JzIDwtIHByZXNlbmNlW3ByZXNlbmNlJGluc3RpdHV0aW9uY29kZSA9PSAiQVJDIiwgXQ0KbWFwMiA8LSBnZXRNYXAocmVzb2x1dGlvbiA9ICJsb3ciKSAjY3JlYXRlcyBhbiBvYmplY3QgY2FsbGVkIG1hcCBhdCBsb3cgcmVzb3VsdGlvbg0KcGxvdChtYXAyLCB4bGltID0gYygtNzAsIC00MyksIHlsaW0gPWMoMzksIDcwKSwgYXNwID0gMSwgbWFpbiA9ICJBcmMgT2NjdXJyZW5jZXMiLCBjb2wgPSAiY29ybnNpbGsiKSAjdGhlIHggYW5kIHkgbGltIGFyZSB0aGUgbG9uZy1sYXQgYm91bmRzIG9mIHRoZSBtYXANCnBvaW50cyhBUkNfb2JzJGRlY2ltYWxMb25naXR1ZGUsIEFSQ19vYnMkZGVjaW1hbExhdGl0dWRlLCBjb2wgPSAicmVkIikgI3RoaXMgYWRkcyBwb2ludHMgdG8gdGhlIG1hcGV0IiwgeGxhYiA9ICJMb25naXR1ZGUiLCB5bGFiID0gIkxhdGl0dWRlIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9iaW8vc2FtcGxpbmdpbnN0aXR1dGlvbnMvQVJDX29jY3VycmVuY2VzX2FsbC5wbmciKSAjdGhpcyBwcmludHMgYSBwbmcgb2YgdGhlIHBsb3QNCmRldi5vZmYoKSAjdGhpcyB0dXJucyBvZmYgdGhlIHByaW50IGNvbW1hbmQNCg0KREZPQ0VOQVJDX29icyA8LSBwcmVzZW5jZVtwcmVzZW5jZSRpbnN0aXR1dGlvbmNvZGUgPT0gIkRGT0NFTkFSQyIsIF0NCm1hcDIgPC0gZ2V0TWFwKHJlc29sdXRpb24gPSAibG93IikgI2NyZWF0ZXMgYW4gb2JqZWN0IGNhbGxlZCBtYXAgYXQgbG93IHJlc291bHRpb24NCnBsb3QobWFwMiwgeGxpbSA9IGMoLTcwLCAtNDMpLCB5bGltID1jKDM5LCA3MCksIGFzcCA9IDEsIG1haW4gPSAiREZPIENlbnRyYWwgJiBBcmN0aWMgT2NjdXJyZW5jZXMiLCAgY29sID0gImNvcm5zaWxrIikgI3RoZSB4IGFuZCB5IGxpbSBhcmUgdGhlIGxvbmctbGF0IGJvdW5kcyBvZiB0aGUgbWFwDQpwb2ludHMoREZPQ0VOQVJDX29icyRkZWNpbWFsTG9uZ2l0dWRlLCBERk9DRU5BUkNfb2JzJGRlY2ltYWxMYXRpdHVkZSwgY29sID0gInJlZCIpICN0aGlzIGFkZHMgcG9pbnRzIHRvIHRoZSBtYXBldCIsIHhsYWIgPSAiTG9uZ2l0dWRlIiwgeWxhYiA9ICJMYXRpdHVkZSIpDQpkZXYuY29weShwbmcsICIuLi9vdXRwdXQvYmlvL3NhbXBsaW5naW5zdGl0dXRpb25zL0RGT0NFTkFSQ19vY2N1cnJlbmNlc19hbGwucG5nIikgI3RoaXMgcHJpbnRzIGEgcG5nIG9mIHRoZSBwbG90DQpkZXYub2ZmKCkgI3RoaXMgdHVybnMgb2ZmIHRoZSBwcmludCBjb21tYW5kDQoNCkRGT0d1bGZfb2JzIDwtIHByZXNlbmNlW3ByZXNlbmNlJGluc3RpdHV0aW9uY29kZSA9PSAiREZPR3VsZiIsIF0NCm1hcDIgPC0gZ2V0TWFwKHJlc29sdXRpb24gPSAibG93IikgI2NyZWF0ZXMgYW4gb2JqZWN0IGNhbGxlZCBtYXAgYXQgbG93IHJlc291bHRpb24NCnBsb3QobWFwMiwgeGxpbSA9IGMoLTcwLCAtNDMpLCB5bGltID1jKDM5LCA3MCksIGFzcCA9IDEsIG1haW4gPSAiREZPIEd1bGYgT2NjdXJyZW5jZXMiLCAgY29sID0gImNvcm5zaWxrIikgI3RoZSB4IGFuZCB5IGxpbSBhcmUgdGhlIGxvbmctbGF0IGJvdW5kcyBvZiB0aGUgbWFwDQpwb2ludHMoREZPR3VsZl9vYnMkZGVjaW1hbExvbmdpdHVkZSwgREZPR3VsZl9vYnMkZGVjaW1hbExhdGl0dWRlLCBjb2wgPSAicmVkIikgI3RoaXMgYWRkcyBwb2ludHMgdG8gdGhlIG1hcGV0IiwgeGxhYiA9ICJMb25naXR1ZGUiLCB5bGFiID0gIkxhdGl0dWRlIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9iaW8vc2FtcGxpbmdpbnN0aXR1dGlvbnMvREZPR3VsZl9vY2N1cnJlbmNlc19hbGwucG5nIikgI3RoaXMgcHJpbnRzIGEgcG5nIG9mIHRoZSBwbG90DQpkZXYub2ZmKCkgI3RoaXMgdHVybnMgb2ZmIHRoZSBwcmludCBjb21tYW5kDQoNCkRGT0lTRE1fb2JzIDwtIHByZXNlbmNlW3ByZXNlbmNlJGluc3RpdHV0aW9uY29kZSA9PSAiREZPSVNETSIsIF0NCm1hcDIgPC0gZ2V0TWFwKHJlc29sdXRpb24gPSAibG93IikgI2NyZWF0ZXMgYW4gb2JqZWN0IGNhbGxlZCBtYXAgYXQgbG93IHJlc291bHRpb24NCnBsb3QobWFwMiwgeGxpbSA9IGMoLTcwLCAtNDMpLCB5bGltID1jKDM5LCA3MCksIGFzcCA9IDEsIG1haW4gPSAiREZPIElTRE0gT2NjdXJyZW5jZXMiLCAgY29sID0gImNvcm5zaWxrIikgI3RoZSB4IGFuZCB5IGxpbSBhcmUgdGhlIGxvbmctbGF0IGJvdW5kcyBvZiB0aGUgbWFwDQpwb2ludHMoREZPSVNETV9vYnMkZGVjaW1hbExvbmdpdHVkZSwgREZPSVNETV9vYnMkZGVjaW1hbExhdGl0dWRlLCBjb2wgPSAicmVkIikgI3RoaXMgYWRkcyBwb2ludHMgdG8gdGhlIG1hcGV0IiwgeGxhYiA9ICJMb25naXR1ZGUiLCB5bGFiID0gIkxhdGl0dWRlIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9iaW8vc2FtcGxpbmdpbnN0aXR1dGlvbnMvREZPSVNETV9vY2N1cnJlbmNlc19hbGwucG5nIikgI3RoaXMgcHJpbnRzIGEgcG5nIG9mIHRoZSBwbG90DQpkZXYub2ZmKCkgI3RoaXMgdHVybnMgb2ZmIHRoZSBwcmludCBjb21tYW5kDQoNCkRGT01UTVNfb2JzIDwtIHByZXNlbmNlW3ByZXNlbmNlJGluc3RpdHV0aW9uY29kZSA9PSAiREZPTVRNUyIsIF0NCm1hcDIgPC0gZ2V0TWFwKHJlc29sdXRpb24gPSAibG93IikgI2NyZWF0ZXMgYW4gb2JqZWN0IGNhbGxlZCBtYXAgYXQgbG93IHJlc291bHRpb24NCnBsb3QobWFwMiwgeGxpbSA9IGMoLTcwLCAtNDMpLCB5bGltID1jKDM5LCA3MCksIGFzcCA9IDEsIG1haW4gPSAiREZPIE1hcml0aW1lcyBPY2N1cnJlbmNlcyIsICBjb2wgPSAiY29ybnNpbGsiKSAjdGhlIHggYW5kIHkgbGltIGFyZSB0aGUgbG9uZy1sYXQgYm91bmRzIG9mIHRoZSBtYXANCnBvaW50cyhERk9NVE1TX29icyRkZWNpbWFsTG9uZ2l0dWRlLCBERk9NVE1TX29icyRkZWNpbWFsTGF0aXR1ZGUsIGNvbCA9ICJyZWQiKSAjdGhpcyBhZGRzIHBvaW50cyB0byB0aGUgbWFwZXQiLCB4bGFiID0gIkxvbmdpdHVkZSIsIHlsYWIgPSAiTGF0aXR1ZGUiKQ0KZGV2LmNvcHkocG5nLCAiLi4vb3V0cHV0L2Jpby9zYW1wbGluZ2luc3RpdHV0aW9ucy9ERk9NVE1TX29jY3VycmVuY2VzX2FsbC5wbmciKSAjdGhpcyBwcmludHMgYSBwbmcgb2YgdGhlIHBsb3QNCmRldi5vZmYoKSAjdGhpcyB0dXJucyBvZmYgdGhlIHByaW50IGNvbW1hbmQNCg0KREZPTkxfb2JzIDwtIHByZXNlbmNlW3ByZXNlbmNlJGluc3RpdHV0aW9uY29kZSA9PSAiREZPTkwiLCBdDQptYXAyIDwtIGdldE1hcChyZXNvbHV0aW9uID0gImxvdyIpICNjcmVhdGVzIGFuIG9iamVjdCBjYWxsZWQgbWFwIGF0IGxvdyByZXNvdWx0aW9uDQpwbG90KG1hcDIsIHhsaW0gPSBjKC03MCwgLTQzKSwgeWxpbSA9YygzOSwgNzApLCBhc3AgPSAxLCBtYWluID0gIkRGTyBOZXdmb3V1bmRsYW5kICYgTGFicmFkb3IgT2NjdXJyZW5jZXMiLCAgY29sID0gImNvcm5zaWxrIikgI3RoZSB4IGFuZCB5IGxpbSBhcmUgdGhlIGxvbmctbGF0IGJvdW5kcyBvZiB0aGUgbWFwDQpwb2ludHMoREZPTkxfb2JzJGRlY2ltYWxMb25naXR1ZGUsIERGT05MX29icyRkZWNpbWFsTGF0aXR1ZGUsIGNvbCA9ICJyZWQiKSAjdGhpcyBhZGRzIHBvaW50cyB0byB0aGUgbWFwZXQiLCB4bGFiID0gIkxvbmdpdHVkZSIsIHlsYWIgPSAiTGF0aXR1ZGUiKQ0KZGV2LmNvcHkocG5nLCAiLi4vb3V0cHV0L2Jpby9zYW1wbGluZ2luc3RpdHV0aW9ucy9ERk9OTF9vY2N1cnJlbmNlc19hbGwucG5nIikgI3RoaXMgcHJpbnRzIGEgcG5nIG9mIHRoZSBwbG90DQpkZXYub2ZmKCkgI3RoaXMgdHVybnMgb2ZmIHRoZSBwcmludCBjb21tYW5kDQoNCkRGT1FDX29icyA8LSBwcmVzZW5jZVtwcmVzZW5jZSRpbnN0aXR1dGlvbmNvZGUgPT0gIkRGT1FDIiwgXQ0KbWFwMiA8LSBnZXRNYXAocmVzb2x1dGlvbiA9ICJsb3ciKSAjY3JlYXRlcyBhbiBvYmplY3QgY2FsbGVkIG1hcCBhdCBsb3cgcmVzb3VsdGlvbg0KcGxvdChtYXAyLCB4bGltID0gYygtNzAsIC00MyksIHlsaW0gPWMoMzksIDcwKSwgYXNwID0gMSwgbWFpbiA9ICJERk8gUXVlYmVjIE9jY3VycmVuY2VzIiwgIGNvbCA9ICJjb3Juc2lsayIpICN0aGUgeCBhbmQgeSBsaW0gYXJlIHRoZSBsb25nLWxhdCBib3VuZHMgb2YgdGhlIG1hcA0KcG9pbnRzKERGT1FDX29icyRkZWNpbWFsTG9uZ2l0dWRlLCBERk9RQ19vYnMkZGVjaW1hbExhdGl0dWRlLCBjb2wgPSAicmVkIikgI3RoaXMgYWRkcyBwb2ludHMgdG8gdGhlIG1hcGV0IiwgeGxhYiA9ICJMb25naXR1ZGUiLCB5bGFiID0gIkxhdGl0dWRlIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9iaW8vc2FtcGxpbmdpbnN0aXR1dGlvbnMvREZPUUNfb2NjdXJyZW5jZXNfYWxsLnBuZyIpICN0aGlzIHByaW50cyBhIHBuZyBvZiB0aGUgcGxvdA0KZGV2Lm9mZigpICN0aGlzIHR1cm5zIG9mZiB0aGUgcHJpbnQgY29tbWFuZA0KDQpNYWluZURNUl9vYnMgPC0gcHJlc2VuY2VbcHJlc2VuY2UkaW5zdGl0dXRpb25jb2RlID09ICJNYWluZURNUiIsIF0NCm1hcDIgPC0gZ2V0TWFwKHJlc29sdXRpb24gPSAibG93IikgI2NyZWF0ZXMgYW4gb2JqZWN0IGNhbGxlZCBtYXAgYXQgbG93IHJlc291bHRpb24NCnBsb3QobWFwMiwgeGxpbSA9IGMoLTcwLCAtNDMpLCB5bGltID1jKDM5LCA3MCksIGFzcCA9IDEsIG1haW4gPSAiTWFpbmUgRE1SIE9jY3VycmVuY2VzIiwgIGNvbCA9ICJjb3Juc2lsayIpICN0aGUgeCBhbmQgeSBsaW0gYXJlIHRoZSBsb25nLWxhdCBib3VuZHMgb2YgdGhlIG1hcA0KcG9pbnRzKE1haW5lRE1SX29icyRkZWNpbWFsTG9uZ2l0dWRlLCBNYWluZURNUl9vYnMkZGVjaW1hbExhdGl0dWRlLCBjb2wgPSAicmVkIikgI3RoaXMgYWRkcyBwb2ludHMgdG8gdGhlIG1hcGV0IiwgeGxhYiA9ICJMb25naXR1ZGUiLCB5bGFiID0gIkxhdGl0dWRlIikNCmRldi5jb3B5KHBuZywgIi4uL291dHB1dC9iaW8vc2FtcGxpbmdpbnN0aXR1dGlvbnMvTWFpbmVETVJfb2NjdXJyZW5jZXNfYWxsLnBuZyIpICN0aGlzIHByaW50cyBhIHBuZyBvZiB0aGUgcGxvdA0KZGV2Lm9mZigpICN0aGlzIHR1cm5zIG9mZiB0aGUgcHJpbnQgY29tbWFuZA0KDQpORUZTQ19vYnMgPC0gcHJlc2VuY2VbcHJlc2VuY2UkaW5zdGl0dXRpb25jb2RlID09ICJORUZTQyIsIF0NCm1hcDIgPC0gZ2V0TWFwKHJlc29sdXRpb24gPSAibG93IikgI2NyZWF0ZXMgYW4gb2JqZWN0IGNhbGxlZCBtYXAgYXQgbG93IHJlc291bHRpb24NCnBsb3QobWFwMiwgeGxpbSA9IGMoLTcwLCAtNDMpLCB5bGltID1jKDM5LCA3MCksIGFzcCA9IDEsIG1haW4gPSAiTkVGU0MgT2NjdXJyZW5jZXMiLCAgY29sID0gImNvcm5zaWxrIikgI3RoZSB4IGFuZCB5IGxpbSBhcmUgdGhlIGxvbmctbGF0IGJvdW5kcyBvZiB0aGUgbWFwDQpwb2ludHMoTkVGU0Nfb2JzJGRlY2ltYWxMb25naXR1ZGUsIE5FRlNDX29icyRkZWNpbWFsTGF0aXR1ZGUsIGNvbCA9ICJyZWQiKSAjdGhpcyBhZGRzIHBvaW50cyB0byB0aGUgbWFwZXQiLCB4bGFiID0gIkxvbmdpdHVkZSIsIHlsYWIgPSAiTGF0aXR1ZGUiKQ0KZGV2LmNvcHkocG5nLCAiLi4vb3V0cHV0L2Jpby9zYW1wbGluZ2luc3RpdHV0aW9ucy9ORUZTQ19vY2N1cnJlbmNlc19hbGwucG5nIikgI3RoaXMgcHJpbnRzIGEgcG5nIG9mIHRoZSBwbG90DQpkZXYub2ZmKCkgI3RoaXMgdHVybnMgb2ZmIHRoZSBwcmludCBjb21tYW5kDQoNClJPTV9vYnMgPC0gcHJlc2VuY2VbcHJlc2VuY2UkaW5zdGl0dXRpb25jb2RlID09ICJST00iLCBdDQptYXAyIDwtIGdldE1hcChyZXNvbHV0aW9uID0gImxvdyIpICNjcmVhdGVzIGFuIG9iamVjdCBjYWxsZWQgbWFwIGF0IGxvdyByZXNvdWx0aW9uDQpwbG90KG1hcDIsIHhsaW0gPSBjKC03MCwgLTQzKSwgeWxpbSA9YygzOSwgNzApLCBhc3AgPSAxLCBtYWluID0gIlJveWFsIE9udGFyaW8gTXVzZXVtIE9jY3VycmVuY2VzIiwgIGNvbCA9ICJjb3Juc2lsayIpICN0aGUgeCBhbmQgeSBsaW0gYXJlIHRoZSBsb25nLWxhdCBib3VuZHMgb2YgdGhlIG1hcA0KcG9pbnRzKFJPTV9vYnMkZGVjaW1hbExvbmdpdHVkZSwgUk9NX29icyRkZWNpbWFsTGF0aXR1ZGUsIGNvbCA9ICJyZWQiKSAjdGhpcyBhZGRzIHBvaW50cyB0byB0aGUgbWFwZXQiLCB4bGFiID0gIkxvbmdpdHVkZSIsIHlsYWIgPSAiTGF0aXR1ZGUiKQ0KZGV2LmNvcHkocG5nLCAiLi4vb3V0cHV0L2Jpby9zYW1wbGluZ2luc3RpdHV0aW9ucy9ST01fb2NjdXJyZW5jZXNfYWxsLnBuZyIpICN0aGlzIHByaW50cyBhIHBuZyBvZiB0aGUgcGxvdA0KYGBgDQoNCiMgY2hlY2sgZm9yIGdlYXIgdHlwZQ0KDQp3aGF0IGFyZSB0aGUgdW5pcXVlIGdlYXIgdHlwZXMgeW91IGhhdmUgaW4geW91ciBwcmVzZW5jZSBkYXRhLCBhbmQgaG93IG1hbnk/DQoNCmBgYHtyIG9ic2VydmF0aW9uIGJ5IGNlbGwgLSB0b3RhbH0NCmdlYXJfY291bnQgPC0gY291bnQocHJlc2VuY2UsICJnZWFyIikNCndyaXRlLmNzdihnZWFyX2NvdW50LCBmaWxlID0gIi4uL291dHB1dC9iaW8vZ2Vhcl9jb3VudC5jc3YiKQ0KZ2Vhcl9jb3VudA0KYGBgDQoNCnNvIHRoZSB2YXN0IG1ham9yaXR5IGFyZSB0cmF3bHMgb2Ygc29tZSB0eXBlLiANCg0KbWFwIHRoZSBnZWFyIHVzYWdlIGluIEFyY2dpcyAoZ2Vhcl90eXBlX21hcCkNCg0KY3JlYXRlIGEgdGFibGUgb2YgZ2VhciB1c2UgYnkgbW9udGgNCg0KYGBge3J9DQpnZWFyYnlfbXRoIDwtIHdpdGgocHJlc2VuY2UsIHRhYmxlKG1vbnRoLCBnZWFyKSkNCndyaXRlLmNzdihnZWFyYnlfbXRoLCBmaWxlID0gIi4uL291dHB1dC9iaW8vZ2Vhcl9ieV9tdGguY3N2IikNCmdlYXJieV9tdGgNCmBgYA0KDQpXaGF0IEkgd2FudCB0byBzZWUgaWYgaWYgdGhlcmUgaXMgYSBtYXJrZWQgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBlbnYuIGNvcnJlbGF0ZXMgb2YgdGhlIHByZXNlbmNlIHBvaW50cyBiZXR3ZWVuIGdlYXIgdHlwZSB1c2VkLiBUaGlzIGlzIGFsc28gdG8gdHJ5IGRlYWwgd2l0aCBkZXRlY3Rpb24gYmlhcyBiZXR3ZWVuIGdlYXIgdHlwZSAoYi9jIHRoZSB3aG9sZSByZWdpb24gaXMgbm90IHVuaWZvcm1seSBzYW1wbGVkIGJ5IHRoZSBzYW1lIGdlYXIgdHlwZSkNCg0KZmlyc3QgY3JlYXRlIGdlYXIgZGF0YXNldHMNCg0KYGBge3IgcHJlc2VuY2UgYnkgZ2Vhcn0NCnByZXNlbmNlJGdlYXIgPC0gYXMuY2hhcmFjdGVyKHByZXNlbmNlJGdlYXIpDQpib3R0b21fdHJhd2wgPC0gc3Vic2V0KHByZXNlbmNlLCBnZWFyID09ICJib3R0b21fdHJhd2wiKQ0KYm90dG9tX3RyYXdsX2FsZnJlZG9fMDMgPC0gc3Vic2V0KHByZXNlbmNlLCBnZWFyID09ICJib3R0b21fdHJhd2xfYWxmcmVkb18wMyIpDQpib3R0b21fdHJhd2xfY2FtcGVsZW5fMTQgPC0gc3Vic2V0KHByZXNlbmNlLCBnZWFyID09ICJib3R0b21fdHJhd2xfY2FtcGVsZW5fMTQiKQ0KYm90dG9tX3RyYXdsX2NhbXBlbGVuXzE4MDAgPC0gc3Vic2V0KHByZXNlbmNlLCBnZWFyID09ICJib3R0b21fdHJhd2xfY2FtcGVsZW5fMTgwMCIpDQpib3R0b21fdHJhd2xfY2FtcGVsZW5fMjEgPC0gc3Vic2V0KHByZXNlbmNlLCBnZWFyID09ICJib3R0b21fdHJhd2xfY2FtcGVsZW5fMjEiKQ0KYm90dG9tX3RyYXdsX2Nvc21vc18yNjAwIDwtIHN1YnNldChwcmVzZW5jZSwgZ2VhciA9PSAiYm90dG9tX3RyYXdsX2Nvc21vc18yNjAwIikNCmJvdHRvbV90cmF3bF93ZXN0ZXJuX0lJQSA8LSBzdWJzZXQocHJlc2VuY2UsIGdlYXIgPT0gImJvdHRvbV90cmF3bF93ZXN0ZXJuX0lJQSIpDQp1bmtub3duIDwtIHN1YnNldChwcmVzZW5jZSwgZ2VhciA9PSAidW5rbm93biIpDQp2ZXJ0aWNhbF9wbGFua3Rvbl90b3cgPC0gc3Vic2V0KHByZXNlbmNlLCBnZWFyID09ICJ2ZXJ0aWNhbF9wbGFua3Rvbl90b3ciKQ0KYGBgDQoNCnBsb3QgYnkgZWFjaCB2YXJpYWJsZSwgbGVzcyAzbSAoMiBzYW1wbGVzKSAxYyAob25lIHNhbXBsZSkgYW5kIDV6ZSAoemVybyBzYW1wbGVzPyEpDQpgYGB7ciBwcmVzZW5jZSBieSBnZWFyIGJ5IHZhcmlhYmxlfQ0KZ2dwbG90KGJvdHRvbV90cmF3bCwgYWVzKHggPSB0ZW1wX3N1cmZhY2UsIGNvbG91ciA9IGdlYXIpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9Ym90dG9tX3RyYXdsX2FsZnJlZG9fMDMsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1ib3R0b21fdHJhd2xfY2FtcGVsZW5fMTQsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1ib3R0b21fdHJhd2xfY2FtcGVsZW5fMTgwMCwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPWJvdHRvbV90cmF3bF9jYW1wZWxlbl8yMSwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPWJvdHRvbV90cmF3bF9jb3Ntb3NfMjYwMCwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPWJvdHRvbV90cmF3bF93ZXN0ZXJuX0lJQSwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPXVua25vd24sIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT12ZXJ0aWNhbF9wbGFua3Rvbl90b3csIG5hLnJtID0gVFJVRSkNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9lbnZfYnlfZ2Vhcl9wbG90cy90ZW1wX3N1cmZhY2VfZ2Vhci5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KGJvdHRvbV90cmF3bCwgYWVzKHggPSB0ZW1wX2RlcHRoLCBjb2xvdXIgPSBnZWFyKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPWJvdHRvbV90cmF3bF9hbGZyZWRvXzAzLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9Ym90dG9tX3RyYXdsX2NhbXBlbGVuXzE0LCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9Ym90dG9tX3RyYXdsX2NhbXBlbGVuXzE4MDAsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1ib3R0b21fdHJhd2xfY2FtcGVsZW5fMjEsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1ib3R0b21fdHJhd2xfY29zbW9zXzI2MDAsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1ib3R0b21fdHJhd2xfd2VzdGVybl9JSUEsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT11bmtub3duLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dmVydGljYWxfcGxhbmt0b25fdG93LCBuYS5ybSA9IFRSVUUpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvZW52X2J5X2dlYXJfcGxvdHMvdGVtcF9kZXB0aF9nZWFyLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QoYm90dG9tX3RyYXdsLCBhZXMoeCA9IGNobF9zdXJmYWNlLCBjb2xvdXIgPSBnZWFyKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPWJvdHRvbV90cmF3bF9hbGZyZWRvXzAzLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9Ym90dG9tX3RyYXdsX2NhbXBlbGVuXzE0LCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9Ym90dG9tX3RyYXdsX2NhbXBlbGVuXzE4MDAsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1ib3R0b21fdHJhd2xfY2FtcGVsZW5fMjEsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1ib3R0b21fdHJhd2xfY29zbW9zXzI2MDAsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1ib3R0b21fdHJhd2xfd2VzdGVybl9JSUEsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT11bmtub3duLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dmVydGljYWxfcGxhbmt0b25fdG93LCBuYS5ybSA9IFRSVUUpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvZW52X2J5X2dlYXJfcGxvdHMvY2hsX3N1cmZhY2VfZ2Vhci5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KGJvdHRvbV90cmF3bCwgYWVzKHggPSBjaGxfZGVwdGgsIGNvbG91ciA9IGdlYXIpKSAgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPWJvdHRvbV90cmF3bF9hbGZyZWRvXzAzLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9Ym90dG9tX3RyYXdsX2NhbXBlbGVuXzE0LCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9Ym90dG9tX3RyYXdsX2NhbXBlbGVuXzE4MDAsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1ib3R0b21fdHJhd2xfY2FtcGVsZW5fMjEsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1ib3R0b21fdHJhd2xfY29zbW9zXzI2MDAsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1ib3R0b21fdHJhd2xfd2VzdGVybl9JSUEsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT11bmtub3duLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dmVydGljYWxfcGxhbmt0b25fdG93LCBuYS5ybSA9IFRSVUUpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvZW52X2J5X2dlYXJfcGxvdHMvY2hsX2RlcHRoX2dlYXIucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdChib3R0b21fdHJhd2wsIGFlcyh4ID0gc2FsaW5pdHlfc3VyZmFjZSwgY29sb3VyID0gZ2VhcikpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1ib3R0b21fdHJhd2xfYWxmcmVkb18wMywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPWJvdHRvbV90cmF3bF9jYW1wZWxlbl8xNCwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPWJvdHRvbV90cmF3bF9jYW1wZWxlbl8xODAwLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9Ym90dG9tX3RyYXdsX2NhbXBlbGVuXzIxLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9Ym90dG9tX3RyYXdsX2Nvc21vc18yNjAwLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9Ym90dG9tX3RyYXdsX3dlc3Rlcm5fSUlBLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dW5rbm93biwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPXZlcnRpY2FsX3BsYW5rdG9uX3RvdywgbmEucm0gPSBUUlVFKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2Vudl9ieV9nZWFyX3Bsb3RzL3NhbGluaXR5X3N1cmZhY2VfZ2Vhci5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KGJvdHRvbV90cmF3bCwgYWVzKHggPSBzYWxpbml0eV9kZXB0aCwgY29sb3VyID0gZ2VhcikpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1ib3R0b21fdHJhd2xfYWxmcmVkb18wMywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPWJvdHRvbV90cmF3bF9jYW1wZWxlbl8xNCwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPWJvdHRvbV90cmF3bF9jYW1wZWxlbl8xODAwLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9Ym90dG9tX3RyYXdsX2NhbXBlbGVuXzIxLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9Ym90dG9tX3RyYXdsX2Nvc21vc18yNjAwLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9Ym90dG9tX3RyYXdsX3dlc3Rlcm5fSUlBLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dW5rbm93biwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPXZlcnRpY2FsX3BsYW5rdG9uX3RvdywgbmEucm0gPSBUUlVFKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2Vudl9ieV9nZWFyX3Bsb3RzL3NhbGluaXR5X2RlcHRoX2dlYXIucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdChib3R0b21fdHJhd2wsIGFlcyh4ID0gbzJfc3VyZmFjZSwgY29sb3VyID0gZ2VhcikpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1ib3R0b21fdHJhd2xfYWxmcmVkb18wMywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPWJvdHRvbV90cmF3bF9jYW1wZWxlbl8xNCwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPWJvdHRvbV90cmF3bF9jYW1wZWxlbl8xODAwLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9Ym90dG9tX3RyYXdsX2NhbXBlbGVuXzIxLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9Ym90dG9tX3RyYXdsX2Nvc21vc18yNjAwLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9Ym90dG9tX3RyYXdsX3dlc3Rlcm5fSUlBLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dW5rbm93biwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPXZlcnRpY2FsX3BsYW5rdG9uX3RvdywgbmEucm0gPSBUUlVFKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2Vudl9ieV9nZWFyX3Bsb3RzL28yX3N1cmZhY2VfZ2Vhci5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KGJvdHRvbV90cmF3bCwgYWVzKHggPSBvMl9kZXB0aCwgY29sb3VyID0gZ2VhcikpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1ib3R0b21fdHJhd2xfYWxmcmVkb18wMywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPWJvdHRvbV90cmF3bF9jYW1wZWxlbl8xNCwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPWJvdHRvbV90cmF3bF9jYW1wZWxlbl8xODAwLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9Ym90dG9tX3RyYXdsX2NhbXBlbGVuXzIxLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9Ym90dG9tX3RyYXdsX2Nvc21vc18yNjAwLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9Ym90dG9tX3RyYXdsX3dlc3Rlcm5fSUlBLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dW5rbm93biwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPXZlcnRpY2FsX3BsYW5rdG9uX3RvdywgbmEucm0gPSBUUlVFKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2Vudl9ieV9nZWFyX3Bsb3RzL28yX2RlcHRoX2dlYXIucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdChib3R0b21fdHJhd2wsIGFlcyh4ID0gbWxwX3N1cmZhY2UsIGNvbG91ciA9IGdlYXIpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9Ym90dG9tX3RyYXdsX2FsZnJlZG9fMDMsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1ib3R0b21fdHJhd2xfY2FtcGVsZW5fMTQsIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1ib3R0b21fdHJhd2xfY2FtcGVsZW5fMTgwMCwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPWJvdHRvbV90cmF3bF9jYW1wZWxlbl8yMSwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPWJvdHRvbV90cmF3bF9jb3Ntb3NfMjYwMCwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPWJvdHRvbV90cmF3bF93ZXN0ZXJuX0lJQSwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPXVua25vd24sIG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT12ZXJ0aWNhbF9wbGFua3Rvbl90b3csIG5hLnJtID0gVFJVRSkNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9lbnZfYnlfZ2Vhcl9wbG90cy9tbHBfZ2Vhci5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KGJvdHRvbV90cmF3bCwgYWVzKHggPSBzc2hfc3VyZmFjZSwgY29sb3VyID0gZ2VhcikpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSkgKyBnZW9tX2RlbnNpdHkoZGF0YT1ib3R0b21fdHJhd2xfYWxmcmVkb18wMywgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPWJvdHRvbV90cmF3bF9jYW1wZWxlbl8xNCwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPWJvdHRvbV90cmF3bF9jYW1wZWxlbl8xODAwLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9Ym90dG9tX3RyYXdsX2NhbXBlbGVuXzIxLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9Ym90dG9tX3RyYXdsX2Nvc21vc18yNjAwLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9Ym90dG9tX3RyYXdsX3dlc3Rlcm5fSUlBLCBuYS5ybSA9IFRSVUUpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dW5rbm93biwgbmEucm0gPSBUUlVFKSArIGdlb21fZGVuc2l0eShkYXRhPXZlcnRpY2FsX3BsYW5rdG9uX3RvdywgbmEucm0gPSBUUlVFKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2Vudl9ieV9nZWFyX3Bsb3RzL3NzaF9nZWFyLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCg0KDQoNCg0KYGBge3J9DQpwYXIobWFyPWMoNyw1LDEsMSkpDQpib3hwbG90KHByZXNlbmNlJHRlbXBfZGVwdGggfiBwcmVzZW5jZSRnZWFyLCB5bGFiID0gIlRlbXBlcmF0dXJlIChLZWx2aW4pIiwgbWFpbiA9ICJUZW1wZXJhdHVyZSBhdCBPYnNlcnZhdGlvbiBEZXB0aCBieSBnZWFyIHR5cGUiLCBsYXMgPSAyKQ0KZGV2LmNvcHkocG5nLCAiLi4vb3V0cHV0L2Vudi9zaW1wbGVfcGxvdHMvdGVtcGVyYXR1cmVfYm94cGxvdF9kZXB0X2dlYXIucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KbG9va3MgbGlrZSBub3QgbXVjaCBkaWZmZXJlbmNlLi4uIHdoYXQgYWJvdXQgYSBrcnVza2FsIHdhbGxhY2UgdGVzdD8NCg0KYGBge3J9DQprcnVza2FsLnRlc3QocHJlc2VuY2UkdGVtcF9kZXB0aCB+IHByZXNlbmNlJGdlYXIpDQpgYGANCk9rIHNvIHRoZXJlIGlzIGEgc3RhdGlzdGljYWxseSBzaWcgZGlmZmVyZW5jZSBzb21ld2hlcmUgaW4gdGhlIHRlbXAgYXQgZGVwdGggcmVwb3J0ZWQgYnkgdGhlIGdlYXIgdHlwZSAoS3J1c2thbC1XYWxsaXMgY2hpLXNxdWFyZWQgPSAyNDguMjcsIGRmID0gNywgcC12YWx1ZSA8IDIuMmUtMTYpDQoNClRvIHNlZSB3aGVyZSB0aGUgZGlmZmVyZW5jZShzKSBhcmUgcnVuIGEgRHVubiB0ZXN0IFphciAoMjAxMCkgc3RhdGVzIHRoYXQgdGhlIER1bm4gdGVzdCAoaW4gdGhlIEZTQSBwYWNrYWdlKSBpcyBhcHByb3ByaWF0ZSBmb3IgZ3JvdXBzIHdpdGggdW5lcXVhbCBudW1iZXJzIG9mIG9ic2VydmF0aW9ucy4oWmFyLCBKLkguIDIwMTAuIEJpb3N0YXRpc3RpY2FsIEFuYWx5c2lzLCA1dGggZWQuICBQZWFyc29uIFByZW50aWNlIEhhbGw6IFVwcGVyIFNhZGRsZSBSaXZlciwgTkouKSBodHRwOi8vcmNvbXBhbmlvbi5vcmcvcmNvbXBhbmlvbi9kXzA2Lmh0bWwNCg0KU0FNIFdIRU4gRFVOTiBJUyBJTlNUQUxMRUQsIEdPIFRPIFJDT01QQU5JT05TLk9SRyBBTkQgTE9PSyBGT1IgRFVOTiAtIENIRUNLIENIUk9NRSBISVNUT1JZIChQUk9CQUJMWSBVTkRFUiBLUlVTS0FMIFdBTExJUykgQUxTTyBNQVAgVEhFIERJU1RSSUJVVElPTiBPRiBUSEVTRSBHRUFSIFRZUEVTDQpgYGB7cn0NCnBhaXJ3aXNlLndpbGNveC50ZXN0KHByZXNlbmNlJHRlbXBfZGVwdGgsIHByZXNlbmNlJGdlYXIsIHAuYWRqPSdib25mZXJyb25pJywgZXhhY3Q9RikNCmBgYA0KDQpkdW5uIHRlc3QgDQpgYGB7cn0NCmdlYXJfdGVtcF9kZXB0aGR1bm4gPC0gZHVublRlc3QocHJlc2VuY2UkdGVtcF9kZXB0aCwgcHJlc2VuY2UkZ2VhciwgbGlzdCA9IFRSVUUpDQpnZWFyX3RlbXBfZGVwdGhkdW5uDQoNCg0KDQp3cml0ZS5jc3YodGFibGUsICIuLi9vdXRwdXQvZW52L2dlYXJfdGVtcF9kZXB0aGR1bm4uY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkNCmBgYA0KDQoNCiN2aWYNCg0KZm9yIHRoaXMgeW91IG5lZWQgdGhlIGpvaW5lZCBkYXRhc2V0LiB0aGlzIHdhcyBjcmVhdGVkIHVuZGVyIG1lcmdpZ19kYXRhc2V0cy5zcmMgYW5kIHRoZSBmaWxlIGlzIC4uL291dHB1dC9iaW8vcHJlc2FiLmNzdg0KDQpgYGB7cn0NCnByZXNhYiA8LSByZWFkLmNzdigiLi4vb3V0cHV0L2Jpby9wcmVzYWIuY3N2IiwgaGVhZGVyID0gVFJVRSkNCmBgYA0KDQoNCmBgYHtyfQ0KdmlmX2FsbHByZXNhYiA8LSB2aWYobG0ob2NjdXJyZW5jZSB+IHRlbXBfc3VyZmFjZSArIHRlbXBfZGVwdGggKyBzYWxpbml0eV9zdXJmYWNlICsgc2FsaW5pdHlfZGVwdGggKyBvMl9zdXJmYWNlICsgbzJfZGVwdGggKyBjaGxfc3VyZmFjZSArIGNobF9kZXB0aCArIGJvdHRvbV9kZXB0aCArIG1scF9zdXJmYWNlICsgc3NoX3N1cmZhY2UgKyBnZWFyICsgbmFvX3NhbXBsZSArIG5hb19wcmV2ICsgbmFvX3dpbnRlciArIGFtb19zYW1wbGUgKyBhbW9fcHJldiArIGFtb193aW50ZXIsIGRhdGEgPSBwcmVzYWIpKQ0Kd3JpdGUuY3N2KHZpZl9hbGxwcmVzYWIsICIuLi9vdXRwdXQvYmlvL3ZpZl9hbGxwcmVzYWIuY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkNCnZpZl9hbGxwcmVzYWINCmBgYA0KaW50ZXJwcmV0IC0gc2VlIGh0dHBzOi8vc3RhdHMuc3RhY2tleGNoYW5nZS5jb20vcXVlc3Rpb25zLzcwNjc5L3doaWNoLXZhcmlhbmNlLWluZmxhdGlvbi1mYWN0b3Itc2hvdWxkLWktYmUtdXNpbmctdGV4dGd2aWYtb3ItdGV4dGd2aWYvOTY1ODQjOTY1ODQNClRvIG1ha2UgR1ZJRnMgY29tcGFyYWJsZSBhY3Jvc3MgZGltZW5zaW9ucywgd2Ugc3VnZ2VzdGVkIHVzaW5nIEdWSUZeKDEvKDIqRGYpKSwgd2hlcmUgRGYgaXMgdGhlIG51bWJlciBvZiBjb2VmZmljaWVudHMgaW4gdGhlIHN1YnNldCAocmVmIGZveCBhbmQgbW90ZXR0ZSAxOTkyIGluIHpvdGVybykNCm9yIHRoZSAyIGNvbnRpbnVvdXMgdmFyaWFibGVzLCBHVklGy4YoMS8oMipEZikpICh3aGljaCBpcyBiYXNpY2FsbHkgdGhlIHNxdWFyZSByb290IG9mIHRoZSBWSUYvR1ZJRiB2YWx1ZSBhcyBERj0xKSBpcyB0aGUgcHJvcG9ydGlvbmFsIGNoYW5nZSBvZiB0aGUgc3RhbmRhcmQgZXJyb3IgYW5kIGNvbmZpZGVuY2UgaW50ZXJ2YWwgb2YgdGhlaXIgY29lZmZpY2llbnRzIGR1ZSB0byB0aGUgbGV2ZWwgb2YgY29sbGluZWFyaXR5LiBUaGUgR1ZJRsuGKDEvKDIqRGYpKSB2YWx1ZSBvZiB0aGUgY2F0ZWdvcmljYWwgdmFyaWFibGUgaXMgYSBzaW1pbGFyIG1lYXN1cmUgZm9yIHRoZSByZWR1Y3Rpb24gaW4gcHJlY2lzaW9uIG9mIHRoZSBjb2VmZmljaWVudHMnIGVzdGltYXRpb24gZHVlIHRvIGNvbGxpbmVhcml0eS4gDQphcHBhcmVudGx5IGkganVzdCBuZWVkIHRvIHNxdWFyZSBHVklGXigxLygyKkRmKSkgYW5kIHRoZW4gdXNlIHRoZSBub3JtYWwgVklGICJydWxlIG9mIHRodW1iIi4uLg0KDQpgYGB7cn0NCnZpZl9hbGxwcmVzYWJfc3EgPC0gcmVhZC5jc3YoIi4uL291dHB1dC9iaW8vdmlmX2FsbHByZXNhYi5jc3YiLCBoZWFkZXIgPSBUUlVFKQ0KdmlmX2FsbHByZXNhYl9zcSRHVklGMkRmc3EgPC0gdmlmX2FsbHByZXNhYl9zcSRHVklGLi4xLi4yLkRmLi5eMg0Kd3JpdGUuY3N2KHZpZl9hbGxwcmVzYWJfc3EsICIuLi9vdXRwdXQvYmlvL3ZpZl9hbGxwcmVzYWJfc3EuY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkNCnZpZl9hbGxwcmVzYWJfc3ENCmBgYA0KDQpBcyBwZXIgU0xSIHN1Z2dlc3Rpb24sIHJlcnVuIHdpdGhvdXQgZ2Vhcg0KDQpgYGB7ciB2aWYgYWxsIGJ1dCBnZWFyfQ0KdmlmX2FsbGJ1dGdlYXIgPC0gdmlmKGxtKG9jY3VycmVuY2UgfiB0ZW1wX3N1cmZhY2UgKyB0ZW1wX2RlcHRoICsgc2FsaW5pdHlfc3VyZmFjZSArIHNhbGluaXR5X2RlcHRoICsgbzJfc3VyZmFjZSArIG8yX2RlcHRoICsgY2hsX3N1cmZhY2UgKyBjaGxfZGVwdGggKyBib3R0b21fZGVwdGggKyBtbHBfc3VyZmFjZSArIHNzaF9zdXJmYWNlICsgbmFvX3NhbXBsZSArIG5hb19wcmV2ICsgbmFvX3dpbnRlciArIGFtb19zYW1wbGUgKyBhbW9fcHJldiArIGFtb193aW50ZXIsIGRhdGEgPSBwcmVzYWIpKQ0Kd3JpdGUuY3N2KHZpZl9hbGxidXRnZWFyLCAiLi4vb3V0cHV0L2Jpby92aWZfYWxsYnV0Z2Vhci5jc3YiLCByb3cubmFtZXMgPSBUUlVFKQ0KdmlmX2FsbGJ1dGdlYXINCmBgYA0KDQpBcyBwZXIgU0xSIHN1Z2dlc3Rpb24sIHJlcnVuIHdpdGhvdXQgZ2VhciBhbmQgbW9zdCBoaWdobHkgY29ycmVsYXRlZCB2YXJpYWJsZXMgDQoNCmBgYHtyIHZpZiB3aXRob3V0IGdlYXIgKyBoaWdoIGNvcnJ9DQp2aWZfYWxsYnV0Z2VhcmhpZ2hseWNvcnIgPC0gdmlmKGxtKG9jY3VycmVuY2UgfiB0ZW1wX3N1cmZhY2UgKyB0ZW1wX2RlcHRoICsgc2FsaW5pdHlfc3VyZmFjZSArIHNhbGluaXR5X2RlcHRoICsgbzJfZGVwdGggKyBjaGxfc3VyZmFjZSArIGJvdHRvbV9kZXB0aCArIG1scF9zdXJmYWNlICsgbmFvX3NhbXBsZSArIG5hb19wcmV2ICsgbmFvX3dpbnRlciArIGFtb19zYW1wbGUgKyBhbW9fd2ludGVyLCBkYXRhID0gcHJlc2FiKSkNCndyaXRlLmNzdih2aWZfYWxsYnV0Z2VhcmhpZ2hseWNvcnIsICIuLi9vdXRwdXQvYmlvL3ZpZl9hbGxidXRnZWFyaGlnaGx5Y29yci5jc3YiLCByb3cubmFtZXMgPSBUUlVFKQ0KdmlmX2FsbGJ1dGdlYXJoaWdobHljb3JyDQpgYGANCg0KDQpBcyBwZXIgU0xSIHN1Z2dlc3Rpb24sIHJlcnVuIHdpdGggZ2VhciBidXQgd2l0aG91dCBtb3N0IGhpZ2hseSBjb3JyZWxhdGVkIHZhcmlhYmxlcw0KDQpgYGB7ciB2aWYgYWxsIGJ1dCBoaWdoIGNvcnJ9DQp2aWZfYWxsYnV0aGlnaGx5Y29yciA8LSB2aWYobG0ob2NjdXJyZW5jZSB+IHRlbXBfc3VyZmFjZSArIHRlbXBfZGVwdGggKyBzYWxpbml0eV9zdXJmYWNlICsgc2FsaW5pdHlfZGVwdGggKyBvMl9kZXB0aCArIGNobF9zdXJmYWNlICsgYm90dG9tX2RlcHRoICsgbWxwX3N1cmZhY2UgKyBuYW9fc2FtcGxlICsgbmFvX3ByZXYgKyBuYW9fd2ludGVyICsgYW1vX3NhbXBsZSArIGFtb193aW50ZXIgKyBnZWFyLCBkYXRhID0gcHJlc2FiKSkNCndyaXRlLmNzdih2aWZfYWxsYnV0aGlnaGx5Y29yciwgIi4uL291dHB1dC9iaW8vdmlmX2FsbGJ1dGhpZ2hseWNvcnIuY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkNCnZpZl9hbGxidXRoaWdobHljb3JyDQoNCnZpZl9hbGxidXRoaWdobHljb3JyX3NxIDwtIHJlYWQuY3N2KCIuLi9vdXRwdXQvYmlvL3ZpZl9hbGxidXRoaWdobHljb3JyLmNzdiIsIGhlYWRlciA9IFRSVUUpDQp2aWZfYWxsYnV0aGlnaGx5Y29ycl9zcSRHVklGMkRmc3EgPC0gdmlmX2FsbGJ1dGhpZ2hseWNvcnJfc3EkR1ZJRi4uMS4uMi5EZi4uXjINCndyaXRlLmNzdih2aWZfYWxsYnV0aGlnaGx5Y29ycl9zcSwgIi4uL291dHB1dC9iaW8vdmlmX2FsbGJ1dGhpZ2hseWNvcnJfc3EuY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkNCnZpZl9hbGxidXRoaWdobHljb3JyX3NxDQpgYGANCg0Kb2sgcmVtb3ZlIG9uZSB2YXJpYWJsZSBhdCBhIHRpbWUgLSBsZWF2ZSBnZWFyIGluDQoNCnJlbW92ZSBhbW9fcHJldg0KYGBge3IgdmlmIGFsbCBidXQgYW1vcHJldn0NCnZpZl9hbGxidXRhbW9fcHJldiA8LSB2aWYobG0ob2NjdXJyZW5jZSB+IHRlbXBfc3VyZmFjZSArIHRlbXBfZGVwdGggKyBzYWxpbml0eV9zdXJmYWNlICsgc2FsaW5pdHlfZGVwdGggKyBvMl9zdXJmYWNlICsgbzJfZGVwdGggKyBjaGxfc3VyZmFjZSArIGNobF9kZXB0aCArIGJvdHRvbV9kZXB0aCArIG1scF9zdXJmYWNlICsgc3NoX3N1cmZhY2UgKyBnZWFyICsgbmFvX3NhbXBsZSArIG5hb19wcmV2ICsgbmFvX3dpbnRlciArIGFtb19zYW1wbGUgKyBhbW9fd2ludGVyLCBkYXRhID0gcHJlc2FiKSkNCndyaXRlLmNzdih2aWZfYWxsYnV0YW1vX3ByZXYsICIuLi9vdXRwdXQvYmlvL3ZpZl9hbGxidXRhbW9fcHJldi5jc3YiLCByb3cubmFtZXMgPSBUUlVFKQ0KdmlmX2FsbGJ1dGFtb19wcmV2DQoNCnZpZl9hbGxidXRhbW9fcHJldl9zcSA8LSByZWFkLmNzdigiLi4vb3V0cHV0L2Jpby92aWZfYWxsYnV0YW1vX3ByZXYuY3N2IiwgaGVhZGVyID0gVFJVRSkNCnZpZl9hbGxidXRhbW9fcHJldl9zcSRHVklGMkRmc3EgPC0gdmlmX2FsbGJ1dGFtb19wcmV2X3NxJEdWSUYuLjEuLjIuRGYuLl4yDQp3cml0ZS5jc3YodmlmX2FsbGJ1dGFtb19wcmV2X3NxLCAiLi4vb3V0cHV0L2Jpby92aWZfYWxsYnV0YW1vX3ByZXZfc3EuY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkNCnZpZl9hbGxidXRhbW9fcHJldl9zcQ0KYGBgDQphbmQgbGVhdmUgZ2VhciBvdXQNCg0KcmVtb3ZlIGFtb19wcmV2ICsgZ2Vhcg0KYGBge3IgdmlmIGFsbCBidXQgYW1vcHJldiArIGdlYXJ9DQp2aWZfYWxsYnV0YW1vX3ByZXZnZWFyIDwtIHZpZihsbShvY2N1cnJlbmNlIH4gdGVtcF9zdXJmYWNlICsgdGVtcF9kZXB0aCArIHNhbGluaXR5X3N1cmZhY2UgKyBzYWxpbml0eV9kZXB0aCArIG8yX3N1cmZhY2UgKyBvMl9kZXB0aCArIGNobF9zdXJmYWNlICsgY2hsX2RlcHRoICsgYm90dG9tX2RlcHRoICsgbWxwX3N1cmZhY2UgKyBzc2hfc3VyZmFjZSArIG5hb19zYW1wbGUgKyBuYW9fcHJldiArIG5hb193aW50ZXIgKyBhbW9fc2FtcGxlICsgYW1vX3dpbnRlciwgZGF0YSA9IHByZXNhYikpDQp3cml0ZS5jc3YodmlmX2FsbGJ1dGFtb19wcmV2Z2VhciwgIi4uL291dHB1dC9iaW8vdmlmX2FsbGJ1dGFtb19wcmV2Z2Vhci5jc3YiLCByb3cubmFtZXMgPSBUUlVFKQ0KdmlmX2FsbGJ1dGFtb19wcmV2Z2Vhcg0KYGBgDQoNCnJlbW92ZSBjaGxfZGVwdGgNCmBgYHtyIHZpZiBhbGwgYnV0IGNobGRlcHRofQ0KdmlmX2FsbGJ1dGNobF9kZXB0aCA8LSB2aWYobG0ob2NjdXJyZW5jZSB+IHRlbXBfc3VyZmFjZSArIHRlbXBfZGVwdGggKyBzYWxpbml0eV9zdXJmYWNlICsgc2FsaW5pdHlfZGVwdGggKyBvMl9zdXJmYWNlICsgbzJfZGVwdGggKyBjaGxfc3VyZmFjZSArIGJvdHRvbV9kZXB0aCArIG1scF9zdXJmYWNlICsgc3NoX3N1cmZhY2UgKyBnZWFyICsgbmFvX3NhbXBsZSArIG5hb19wcmV2ICsgbmFvX3dpbnRlciArIGFtb19zYW1wbGUgKyBhbW9fcHJldiArIGFtb193aW50ZXIsIGRhdGEgPSBwcmVzYWIpKQ0Kd3JpdGUuY3N2KHZpZl9hbGxidXRjaGxfZGVwdGgsICIuLi9vdXRwdXQvYmlvL3ZpZl9hbGxidXRjaGxfZGVwdGguY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkNCnZpZl9hbGxidXRjaGxfZGVwdGgNCg0KdmlmX2FsbGJ1dGNobF9kZXB0aF9zcSA8LSByZWFkLmNzdigiLi4vb3V0cHV0L2Jpby92aWZfYWxsYnV0Y2hsX2RlcHRoLmNzdiIsIGhlYWRlciA9IFRSVUUpDQp2aWZfYWxsYnV0Y2hsX2RlcHRoX3NxJEdWSUYyRGZzcSA8LSB2aWZfYWxsYnV0Y2hsX2RlcHRoX3NxJEdWSUYuLjEuLjIuRGYuLl4yDQp3cml0ZS5jc3YodmlmX2FsbGJ1dGNobF9kZXB0aF9zcSwgIi4uL291dHB1dC9iaW8vdmlmX2FsbGJ1dGNobF9kZXB0aF9zcS5jc3YiLCByb3cubmFtZXMgPSBUUlVFKQ0KdmlmX2FsbGJ1dGNobF9kZXB0aF9zcQ0KYGBgDQoNCnJlbW92ZSBjaGxfZGVwdGggYW5kIGdlYXINCmBgYHtyIHZpZiBhbGwgYnV0IGNobGRlcHRoK2dlYXJ9DQp2aWZfYWxsYnV0Y2hsX2RlcHRoZ2VhciA8LSB2aWYobG0ob2NjdXJyZW5jZSB+IHRlbXBfc3VyZmFjZSArIHRlbXBfZGVwdGggKyBzYWxpbml0eV9zdXJmYWNlICsgc2FsaW5pdHlfZGVwdGggKyBvMl9zdXJmYWNlICsgbzJfZGVwdGggKyBjaGxfc3VyZmFjZSArIGJvdHRvbV9kZXB0aCArIG1scF9zdXJmYWNlICsgc3NoX3N1cmZhY2UgKyBuYW9fc2FtcGxlICsgbmFvX3ByZXYgKyBuYW9fd2ludGVyICsgYW1vX3NhbXBsZSArIGFtb19wcmV2ICsgYW1vX3dpbnRlciwgZGF0YSA9IHByZXNhYikpDQp3cml0ZS5jc3YodmlmX2FsbGJ1dGNobF9kZXB0aGdlYXIsICIuLi9vdXRwdXQvYmlvL3ZpZl9hbGxidXRjaGxfZGVwdGhnZWFyLmNzdiIsIHJvdy5uYW1lcyA9IFRSVUUpDQp2aWZfYWxsYnV0Y2hsX2RlcHRoZ2Vhcg0KYGBgDQoNCg0KcmVtb3ZlIHNzaF9zdXJmYWNlDQpgYGB7ciB2aWYgYWxsIGJ1dCBzc2h9DQp2aWZfYWxsYnV0c3NoX3N1cmZhY2UgPC0gdmlmKGxtKG9jY3VycmVuY2UgfiB0ZW1wX3N1cmZhY2UgKyB0ZW1wX2RlcHRoICsgc2FsaW5pdHlfc3VyZmFjZSArIHNhbGluaXR5X2RlcHRoICsgbzJfc3VyZmFjZSArIG8yX2RlcHRoICsgY2hsX3N1cmZhY2UgKyBjaGxfZGVwdGggKyBib3R0b21fZGVwdGggKyBtbHBfc3VyZmFjZSArIGdlYXIgKyBuYW9fc2FtcGxlICsgbmFvX3ByZXYgKyBuYW9fd2ludGVyICsgYW1vX3NhbXBsZSArIGFtb19wcmV2ICsgYW1vX3dpbnRlciwgZGF0YSA9IHByZXNhYikpDQp3cml0ZS5jc3YodmlmX2FsbGJ1dHNzaF9zdXJmYWNlLCAiLi4vb3V0cHV0L2Jpby92aWZfYWxsYnV0c3NoX3N1cmZhY2UuY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkNCnZpZl9hbGxidXRzc2hfc3VyZmFjZQ0KDQp2aWZfYWxsYnV0c3NoX3N1cmZhY2Vfc3EgPC0gcmVhZC5jc3YoIi4uL291dHB1dC9iaW8vdmlmX2FsbGJ1dHNzaF9zdXJmYWNlLmNzdiIsIGhlYWRlciA9IFRSVUUpDQp2aWZfYWxsYnV0c3NoX3N1cmZhY2Vfc3EkR1ZJRjJEZnNxIDwtIHZpZl9hbGxidXRzc2hfc3VyZmFjZV9zcSRHVklGLi4xLi4yLkRmLi5eMg0Kd3JpdGUuY3N2KHZpZl9hbGxidXRzc2hfc3VyZmFjZV9zcSwgIi4uL291dHB1dC9iaW8vdmlmX2FsbGJ1dHNzaF9zdXJmYWNlX3NxLmNzdiIsIHJvdy5uYW1lcyA9IFRSVUUpDQp2aWZfYWxsYnV0c3NoX3N1cmZhY2Vfc3ENCmBgYA0KDQpyZW1vdmUgc3NoX3N1cmZhY2UgJiBnZWFyDQpgYGB7ciB2aWYgYWxsIGJ1dCBzc2grZ2Vhcn0NCnZpZl9hbGxidXRzc2hfc3VyZmFjZWdlYXIgPC0gdmlmKGxtKG9jY3VycmVuY2UgfiB0ZW1wX3N1cmZhY2UgKyB0ZW1wX2RlcHRoICsgc2FsaW5pdHlfc3VyZmFjZSArIHNhbGluaXR5X2RlcHRoICsgbzJfc3VyZmFjZSArIG8yX2RlcHRoICsgY2hsX3N1cmZhY2UgKyBjaGxfZGVwdGggKyBib3R0b21fZGVwdGggKyBtbHBfc3VyZmFjZSArIG5hb19zYW1wbGUgKyBuYW9fcHJldiArIG5hb193aW50ZXIgKyBhbW9fc2FtcGxlICsgYW1vX3ByZXYgKyBhbW9fd2ludGVyLCBkYXRhID0gcHJlc2FiKSkNCndyaXRlLmNzdih2aWZfYWxsYnV0c3NoX3N1cmZhY2VnZWFyLCAiLi4vb3V0cHV0L2Jpby92aWZfYWxsYnV0c3NoX3N1cmZhY2VnZWFyLmNzdiIsIHJvdy5uYW1lcyA9IFRSVUUpDQp2aWZfYWxsYnV0c3NoX3N1cmZhY2VnZWFyDQpgYGANCg0KcmVtb3ZlIG8yX3N1cmZhY2UNCmBgYHtyIHZpZiBhbGwgYnV0IG8yc3VyZmFjZX0NCnZpZl9hbGxidXRvMl9zdXJmYWNlIDwtIHZpZihsbShvY2N1cnJlbmNlIH4gdGVtcF9zdXJmYWNlICsgdGVtcF9kZXB0aCArIHNhbGluaXR5X3N1cmZhY2UgKyBzYWxpbml0eV9kZXB0aCArIG8yX2RlcHRoICsgY2hsX3N1cmZhY2UgKyBjaGxfZGVwdGggKyBib3R0b21fZGVwdGggKyBtbHBfc3VyZmFjZSArIHNzaF9zdXJmYWNlICsgZ2VhciArIG5hb19zYW1wbGUgKyBuYW9fcHJldiArIG5hb193aW50ZXIgKyBhbW9fc2FtcGxlICsgYW1vX3ByZXYgKyBhbW9fd2ludGVyLCBkYXRhID0gcHJlc2FiKSkNCndyaXRlLmNzdih2aWZfYWxsYnV0bzJfc3VyZmFjZSwgIi4uL291dHB1dC9iaW8vdmlmX2FsbGJ1dG8yX3N1cmZhY2UuY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkNCnZpZl9hbGxidXRvMl9zdXJmYWNlDQoNCnZpZl9hbGxidXRvMl9zdXJmYWNlX3NxIDwtIHJlYWQuY3N2KCIuLi9vdXRwdXQvYmlvL3ZpZl9hbGxidXRvMl9zdXJmYWNlLmNzdiIsIGhlYWRlciA9IFRSVUUpDQp2aWZfYWxsYnV0bzJfc3VyZmFjZV9zcSRHVklGMkRmc3EgPC0gdmlmX2FsbGJ1dG8yX3N1cmZhY2Vfc3EkR1ZJRi4uMS4uMi5EZi4uXjINCndyaXRlLmNzdih2aWZfYWxsYnV0bzJfc3VyZmFjZV9zcSwgIi4uL291dHB1dC9iaW8vdmlmX2FsbGJ1dG8yX3N1cmZhY2Vfc3EuY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkNCnZpZl9hbGxidXRvMl9zdXJmYWNlX3NxDQpgYGANCg0KcmVtb3ZlIG8yX3N1cmZhY2UgJiBnZWFyDQpgYGB7ciB2aWYgYWxsIGJ1dCBvMnN1cmZhY2UrZ2Vhcn0NCnZpZl9hbGxidXRvMl9zdXJmYWNlZ2VhciA8LSB2aWYobG0ob2NjdXJyZW5jZSB+IHRlbXBfc3VyZmFjZSArIHRlbXBfZGVwdGggKyBzYWxpbml0eV9zdXJmYWNlICsgc2FsaW5pdHlfZGVwdGggKyBvMl9kZXB0aCArIGNobF9zdXJmYWNlICsgY2hsX2RlcHRoICsgYm90dG9tX2RlcHRoICsgbWxwX3N1cmZhY2UgKyBzc2hfc3VyZmFjZSArIG5hb19zYW1wbGUgKyBuYW9fcHJldiArIG5hb193aW50ZXIgKyBhbW9fc2FtcGxlICsgYW1vX3ByZXYgKyBhbW9fd2ludGVyLCBkYXRhID0gcHJlc2FiKSkNCndyaXRlLmNzdih2aWZfYWxsYnV0bzJfc3VyZmFjZWdlYXIsICIuLi9vdXRwdXQvYmlvL3ZpZl9hbGxidXRvMl9zdXJmYWNlZ2Vhci5jc3YiLCByb3cubmFtZXMgPSBUUlVFKQ0KdmlmX2FsbGJ1dG8yX3N1cmZhY2VnZWFyDQpgYGANCg0KYXMgcGVyIFNMUiBjaGF0IGphbiAyMzogDQoNCnJlbW92ZSBzYWxpbml0eV9zdXJmYWNlIG9ubHkNCmBgYHtyIHZpZiBhbGwgYnV0IHNhbHN1cmZhY2V9DQp2aWZfYWxsYnV0c2FsaW5pdHlzdXJmYWNlIDwtIHZpZihsbShvY2N1cnJlbmNlIH4gdGVtcF9zdXJmYWNlICsgdGVtcF9kZXB0aCArIHNhbGluaXR5X2RlcHRoICsgbzJfc3VyZmFjZSArIG8yX2RlcHRoICsgY2hsX3N1cmZhY2UgKyBjaGxfZGVwdGggKyBib3R0b21fZGVwdGggKyBtbHBfc3VyZmFjZSArIHNzaF9zdXJmYWNlICsgZ2VhciArIG5hb19zYW1wbGUgKyBuYW9fcHJldiArIG5hb193aW50ZXIgKyBhbW9fc2FtcGxlICsgYW1vX3ByZXYgKyBhbW9fd2ludGVyLCBkYXRhID0gcHJlc2FiKSkNCndyaXRlLmNzdih2aWZfYWxsYnV0c2FsaW5pdHlzdXJmYWNlLCAiLi4vb3V0cHV0L2Jpby92aWZfYWxsYnV0c2FsaW5pdHlzdXJmYWNlLmNzdiIsIHJvdy5uYW1lcyA9IFRSVUUpDQp2aWZfYWxsYnV0c2FsaW5pdHlzdXJmYWNlDQoNCnZpZl9hbGxidXRzYWxpbml0eXN1cmZhY2Vfc3EgPC0gcmVhZC5jc3YoIi4uL291dHB1dC9iaW8vdmlmX2FsbGJ1dHNhbGluaXR5c3VyZmFjZS5jc3YiLCBoZWFkZXIgPSBUUlVFKQ0KdmlmX2FsbGJ1dHNhbGluaXR5c3VyZmFjZV9zcSRHVklGMkRmc3EgPC0gdmlmX2FsbGJ1dHNhbGluaXR5c3VyZmFjZV9zcSRHVklGLi4xLi4yLkRmLi5eMg0Kd3JpdGUuY3N2KHZpZl9hbGxidXRzYWxpbml0eXN1cmZhY2Vfc3EsICIuLi9vdXRwdXQvYmlvL3ZpZl9hbGxidXRzYWxpbml0eXN1cmZhY2Vfc3EuY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkNCnZpZl9hbGxidXRzYWxpbml0eXN1cmZhY2Vfc3ENCmBgYA0KYW5kIHdpdGhvdXQgZ2Vhcg0KDQpgYGB7ciB2aWYgYWxsIGJ1dCBzYWxzdXJmYWNlK2dlYXJ9DQp2aWZfYWxsYnV0c2FsaW5pdHlzdXJmYWNlZ2VhciA8LSB2aWYobG0ob2NjdXJyZW5jZSB+IHRlbXBfc3VyZmFjZSArIHRlbXBfZGVwdGggKyBzYWxpbml0eV9kZXB0aCArIG8yX3N1cmZhY2UgKyBvMl9kZXB0aCArIGNobF9zdXJmYWNlICsgY2hsX2RlcHRoICsgYm90dG9tX2RlcHRoICsgbWxwX3N1cmZhY2UgKyBzc2hfc3VyZmFjZSArIG5hb19zYW1wbGUgKyBuYW9fcHJldiArIG5hb193aW50ZXIgKyBhbW9fc2FtcGxlICsgYW1vX3ByZXYgKyBhbW9fd2ludGVyLCBkYXRhID0gcHJlc2FiKSkNCndyaXRlLmNzdih2aWZfYWxsYnV0c2FsaW5pdHlzdXJmYWNlZ2VhciwgIi4uL291dHB1dC9iaW8vdmlmX2FsbGJ1dHNhbGluaXR5c3VyZmFjZWdlYXIuY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkNCnZpZl9hbGxidXRzYWxpbml0eXN1cmZhY2VnZWFyDQpgYGANCg0Kbm93IHJlbW92ZSB0ZW1wX3N1cmZhY2UgcGx1cyBoaWdobHkgY29ycmVsYXRlZA0KYGBge3IgdmlmIGFsbGJ1dCBoaWdoIGNvcnIgKyB0ZW1wIHN1cmZhY2UvZ2Vhci9ub2dlYXJ9DQojd2l0aCBnZWFyDQp2aWZfYWxsYnV0aGlnaGNvcnJ0ZW1wc3VyZmFjZSA8LSB2aWYobG0ob2NjdXJyZW5jZSB+IHRlbXBfZGVwdGggKyBzYWxpbml0eV9zdXJmYWNlICsgc2FsaW5pdHlfZGVwdGggKyBvMl9kZXB0aCArIGNobF9zdXJmYWNlICsgYm90dG9tX2RlcHRoICsgbWxwX3N1cmZhY2UgKyBnZWFyICsgbmFvX3NhbXBsZSArIG5hb19wcmV2ICsgbmFvX3dpbnRlciArIGFtb19zYW1wbGUgKyBhbW9fd2ludGVyLCBkYXRhID0gcHJlc2FiKSkNCndyaXRlLmNzdih2aWZfYWxsYnV0aGlnaGNvcnJ0ZW1wc3VyZmFjZSwgIi4uL291dHB1dC9iaW8vdmlmX2FsbGJ1dGhpZ2hjb3JydGVtcHN1cmZhY2UuY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkNCnZpZl9hbGxidXRoaWdoY29ycnRlbXBzdXJmYWNlDQoNCnZpZl9hbGxidXRoaWdoY29ycnRlbXBzdXJmYWNlX3NxIDwtIHJlYWQuY3N2KCIuLi9vdXRwdXQvYmlvL3ZpZl9hbGxidXRoaWdoY29ycnRlbXBzdXJmYWNlLmNzdiIsIGhlYWRlciA9IFRSVUUpDQp2aWZfYWxsYnV0aGlnaGNvcnJ0ZW1wc3VyZmFjZV9zcSRHVklGMkRmc3EgPC0gdmlmX2FsbGJ1dGhpZ2hjb3JydGVtcHN1cmZhY2Vfc3EkR1ZJRi4uMS4uMi5EZi4uXjINCndyaXRlLmNzdih2aWZfYWxsYnV0aGlnaGNvcnJ0ZW1wc3VyZmFjZV9zcSwgIi4uL291dHB1dC9iaW8vdmlmX2FsbGJ1dGhpZ2hjb3JydGVtcHN1cmZhY2Vfc3EuY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkNCnZpZl9hbGxidXRoaWdoY29ycnRlbXBzdXJmYWNlX3NxDQoNCiN3aXRob3V0IGdlYXINCnZpZl9hbGxidXRoaWdoY29ycnRlbXBzdXJmYWNlZ2VhciA8LSB2aWYobG0ob2NjdXJyZW5jZSB+IHRlbXBfZGVwdGggKyBzYWxpbml0eV9zdXJmYWNlICsgc2FsaW5pdHlfZGVwdGggKyBvMl9kZXB0aCArIGNobF9zdXJmYWNlICsgYm90dG9tX2RlcHRoICsgbWxwX3N1cmZhY2UgKyBuYW9fc2FtcGxlICsgbmFvX3ByZXYgKyBuYW9fd2ludGVyICsgYW1vX3NhbXBsZSArIGFtb193aW50ZXIsIGRhdGEgPSBwcmVzYWIpKQ0Kd3JpdGUuY3N2KHZpZl9hbGxidXRoaWdoY29ycnRlbXBzdXJmYWNlZ2VhciwgIi4uL291dHB1dC9iaW8vdmlmX2FsbGJ1dGhpZ2hjb3JydGVtcHN1cmZhY2VnZWFyLmNzdiIsIHJvdy5uYW1lcyA9IFRSVUUpDQp2aWZfYWxsYnV0aGlnaGNvcnJ0ZW1wc3VyZmFjZWdlYXINCmBgYA0KDQpub3cgcmVtb3ZlIHRlbXBfc3VyZmFjZSBwbHVzIHNhbGluaXR5X3N1cmZhY2UNCmBgYHtyIHZpZiBhbGxidXQgdGVtcCArIHNhbGluaXR5IHN1cmZhY2UvZ2Vhci9ub2dlYXJ9DQojd2l0aCBnZWFyDQp2aWZfYWxsYnV0dGVtcHNhbHN1cmZhY2UgPC0gdmlmKGxtKG9jY3VycmVuY2UgfiB0ZW1wX2RlcHRoICsgc2FsaW5pdHlfZGVwdGggKyBvMl9zdXJmYWNlICsgbzJfZGVwdGggKyBjaGxfc3VyZmFjZSArIGNobF9kZXB0aCArIGJvdHRvbV9kZXB0aCArIG1scF9zdXJmYWNlICsgc3NoX3N1cmZhY2UgKyBnZWFyICsgbmFvX3NhbXBsZSArIG5hb19wcmV2ICsgbmFvX3dpbnRlciArIGFtb19zYW1wbGUgKyBhbW9fcHJldiArIGFtb193aW50ZXIsIGRhdGEgPSBwcmVzYWIpKQ0Kd3JpdGUuY3N2KHZpZl9hbGxidXR0ZW1wc2Fsc3VyZmFjZSwgIi4uL291dHB1dC9iaW8vdmlmX2FsbGJ1dHRlbXBzYWxzdXJmYWNlLmNzdiIsIHJvdy5uYW1lcyA9IFRSVUUpDQp2aWZfYWxsYnV0dGVtcHNhbHN1cmZhY2UNCg0KdmlmX2FsbGJ1dHRlbXBzYWxzdXJmYWNlX3NxIDwtIHJlYWQuY3N2KCIuLi9vdXRwdXQvYmlvL3ZpZl9hbGxidXR0ZW1wc2Fsc3VyZmFjZS5jc3YiLCBoZWFkZXIgPSBUUlVFKQ0KdmlmX2FsbGJ1dHRlbXBzYWxzdXJmYWNlX3NxJEdWSUYyRGZzcSA8LSB2aWZfYWxsYnV0dGVtcHNhbHN1cmZhY2Vfc3EkR1ZJRi4uMS4uMi5EZi4uXjINCndyaXRlLmNzdih2aWZfYWxsYnV0dGVtcHNhbHN1cmZhY2Vfc3EsICIuLi9vdXRwdXQvYmlvL3ZpZl9hbGxidXR0ZW1wc2Fsc3VyZmFjZV9zcS5jc3YiLCByb3cubmFtZXMgPSBUUlVFKQ0KdmlmX2FsbGJ1dHRlbXBzYWxzdXJmYWNlX3NxDQoNCiN3aXRob3V0IGdlYXINCnZpZl9hbGxidXR0ZW1wc2Fsc3VyZmFjZWdlYXIgPC0gdmlmKGxtKG9jY3VycmVuY2UgfiB0ZW1wX2RlcHRoICsgc2FsaW5pdHlfZGVwdGggKyBvMl9zdXJmYWNlICsgbzJfZGVwdGggKyBjaGxfc3VyZmFjZSArIGNobF9kZXB0aCArIGJvdHRvbV9kZXB0aCArIG1scF9zdXJmYWNlICsgc3NoX3N1cmZhY2UgKyBuYW9fc2FtcGxlICsgbmFvX3ByZXYgKyBuYW9fd2ludGVyICsgYW1vX3NhbXBsZSArIGFtb19wcmV2ICsgYW1vX3dpbnRlciwgZGF0YSA9IHByZXNhYikpDQp3cml0ZS5jc3YodmlmX2FsbGJ1dHRlbXBzYWxzdXJmYWNlZ2VhciwgIi4uL291dHB1dC9iaW8vdmlmX2FsbGJ1dHRlbXBzYWxzdXJmYWNlZ2Vhci5jc3YiLCByb3cubmFtZXMgPSBUUlVFKQ0KdmlmX2FsbGJ1dHRlbXBzYWxzdXJmYWNlZ2Vhcg0KYGBgDQoNCm5vdyByZW1vdmUgdGVtcF9zdXJmYWNlIHBsdXMgc2FsaW5pdHlfc3VyZmFjZSArIGhpZ2hseSBjb3JyZWxhdGVkDQpgYGB7ciB2aWYgYWxsYnV0IGhpZ2ggY29yciArICB0ZW1wICsgc2FsaW5pdHkgc3VyZmFjZS9nZWFyL25vZ2Vhcn0NCiN3aXRoIGdlYXINCnZpZl9hbGxidXRoaWdoY29ycnRlbXBzYWxzdXJmYWNlIDwtIHZpZihsbShvY2N1cnJlbmNlIH4gdGVtcF9kZXB0aCArIHNhbGluaXR5X2RlcHRoICsgbzJfZGVwdGggKyBjaGxfc3VyZmFjZSArIGJvdHRvbV9kZXB0aCArIG1scF9zdXJmYWNlICsgZ2VhciArIG5hb19zYW1wbGUgKyBuYW9fcHJldiArIG5hb193aW50ZXIgKyBhbW9fc2FtcGxlICsgYW1vX3dpbnRlciwgZGF0YSA9IHByZXNhYikpDQp3cml0ZS5jc3YodmlmX2FsbGJ1dGhpZ2hjb3JydGVtcHNhbHN1cmZhY2UsICIuLi9vdXRwdXQvYmlvL3ZpZl9hbGxidXRoaWdoY29ycnRlbXBzYWxzdXJmYWNlLmNzdiIsIHJvdy5uYW1lcyA9IFRSVUUpDQp2aWZfYWxsYnV0aGlnaGNvcnJ0ZW1wc2Fsc3VyZmFjZQ0KDQp2aWZfYWxsYnV0aGlnaGNvcnJ0ZW1wc2Fsc3VyZmFjZV9zcSA8LSByZWFkLmNzdigiLi4vb3V0cHV0L2Jpby92aWZfYWxsYnV0aGlnaGNvcnJ0ZW1wc2Fsc3VyZmFjZS5jc3YiLCBoZWFkZXIgPSBUUlVFKQ0KdmlmX2FsbGJ1dGhpZ2hjb3JydGVtcHNhbHN1cmZhY2Vfc3EkR1ZJRjJEZnNxIDwtIHZpZl9hbGxidXRoaWdoY29ycnRlbXBzYWxzdXJmYWNlX3NxJEdWSUYuLjEuLjIuRGYuLl4yDQp3cml0ZS5jc3YodmlmX2FsbGJ1dGhpZ2hjb3JydGVtcHNhbHN1cmZhY2Vfc3EsICIuLi9vdXRwdXQvYmlvL3ZpZl9hbGxidXRoaWdoY29ycnRlbXBzYWxzdXJmYWNlX3NxLmNzdiIsIHJvdy5uYW1lcyA9IFRSVUUpDQp2aWZfYWxsYnV0aGlnaGNvcnJ0ZW1wc2Fsc3VyZmFjZV9zcQ0KDQojd2l0aG91dCBnZWFyDQp2aWZfYWxsYnV0aGlnaGNvcnJ0ZW1wc2Fsc3VyZmFjZWdlYXIgPC0gdmlmKGxtKG9jY3VycmVuY2UgfiB0ZW1wX2RlcHRoICsgc2FsaW5pdHlfZGVwdGggKyBvMl9kZXB0aCArIGNobF9zdXJmYWNlICsgYm90dG9tX2RlcHRoICsgbWxwX3N1cmZhY2UgKyBuYW9fc2FtcGxlICsgbmFvX3ByZXYgKyBuYW9fd2ludGVyICsgYW1vX3NhbXBsZSArIGFtb193aW50ZXIsIGRhdGEgPSBwcmVzYWIpKQ0Kd3JpdGUuY3N2KHZpZl9hbGxidXRoaWdoY29ycnRlbXBzYWxzdXJmYWNlZ2VhciwgIi4uL291dHB1dC9iaW8vdmlmX2FsbGJ1dGhpZ2hjb3JydGVtcHNhbHN1cmZhY2VnZWFyLmNzdiIsIHJvdy5uYW1lcyA9IFRSVUUpDQp2aWZfYWxsYnV0aGlnaGNvcnJ0ZW1wc2Fsc3VyZmFjZWdlYXINCmBgYA0KDQpKdXN0IG91dCBvZiBjdXJpb3NpdHksIGEgdmlmIHdpbGwgYWxsIGJ1dCBidXQgYXRtb3MgZHJpdmVycw0KDQpgYGB7cn0NCnZpZl9hbGxidXRuYW9hbW8gPC0gdmlmKGxtKG9jY3VycmVuY2UgfiB0ZW1wX3N1cmZhY2UgKyB0ZW1wX2RlcHRoICsgc2FsaW5pdHlfc3VyZmFjZSArIHNhbGluaXR5X2RlcHRoICsgbzJfc3VyZmFjZSArIG8yX2RlcHRoICsgY2hsX3N1cmZhY2UgKyBjaGxfZGVwdGggKyBib3R0b21fZGVwdGggKyBtbHBfc3VyZmFjZSArIHNzaF9zdXJmYWNlICsgZ2VhciwgZGF0YSA9IHByZXNhYikpDQp3cml0ZS5jc3YodmlmX2FsbGJ1dG5hb2FtbywgIi4uL291dHB1dC9iaW8vdmlmX2FsbGJ1dG5hb2Ftby5jc3YiLCByb3cubmFtZXMgPSBUUlVFKQ0KdmlmX2FsbGJ1dG5hb2Ftbw0KDQp2aWZfYWxsYnV0bmFvYW1vX3NxIDwtIHJlYWQuY3N2KCIuLi9vdXRwdXQvYmlvL3ZpZl9hbGxidXRuYW9hbW8uY3N2IiwgaGVhZGVyID0gVFJVRSkNCnZpZl9hbGxidXRuYW9hbW9fc3EkR1ZJRjJEZnNxIDwtIHZpZl9hbGxidXRuYW9hbW9fc3EkR1ZJRi4uMS4uMi5EZi4uXjINCndyaXRlLmNzdih2aWZfYWxsYnV0bmFvYW1vX3NxLCAiLi4vb3V0cHV0L2Jpby92aWZfYWxsYnV0bmFvYW1vX3NxLmNzdiIsIHJvdy5uYW1lcyA9IFRSVUUpDQp2aWZfYWxsYnV0bmFvYW1vX3NxDQpgYGANCg0KIyBjaGVjayB0byBzZWUgaG93IG1hbnkgY2VsbHMgaGF2ZSA+MSBwb2ludCBwZXIgdGltZXNsaWNlDQoNCnRoaXMgbmVlZHMgdG8gYmUgM0Qgc28geW91IG5lZWQgdG8gY3JlYXRlIGEgY2VsbF9pZF8zZA0KYGBge3IgY2VsbF9pZF8zZH0NCnByZXNhYiRjZWxsX2lkXzNkIDwtIHBhc3RlKHByZXNhYiRjZWxsX2lkLCBwcmVzYWIkZGVwdGhsYXllcm5vLCBzZXA9Il8iKSAjY3JlYXRlIGEgbmV3IGNvbHVtbiB0aGF0IGlzIGEgdW5pcXVlIGNlbGxfaWQgJiBkZXB0aCBJRC4gDQpoZWFkKHByZXNhYikNCmBgYA0KYW5kIG5vdyBkbyBvbmUgd2l0aCBhIHRpbWVzbGljZSBsYWJlbA0KYGBge3IgY2VsbF9pZF94eXp0fQ0KcHJlc2FiJGNlbGxfaWRfeHl6dCA8LSBwYXN0ZShwcmVzYWIkY2VsbF9pZF8zZCwgcHJlc2FiJHllYXIsIHByZXNhYiRtb250aCwgc2VwPSJfIikgI2NyZWF0ZSBhIG5ldyBjb2x1bW4gdGhhdCBpcyBhIHVuaXF1ZSBjZWxsX2lkICYgZGVwdGggSUQuIA0KaGVhZChwcmVzYWIpDQp3cml0ZS5jc3YocHJlc2FiLCAiLi4vb3V0cHV0L2Jpby9wcmVzYWJfY2VsbGlkX3h5enQuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpDQpgYGANCg0KDQpiZWNhdXNlIGJhY2tncm91bmQgcG9pbnRzIGNhbiBsYW5kIGluIHRoZSBzYW1lIHh5enQsIHN1YnNldCB0aGUgZGF0YXNldCB0byBiZSBvbmx5IHByZXNlbmNlcw0KDQpgYGB7cn0NCnByZXNlbmNlZHVwIDwtIHN1YnNldChwcmVzYWIsIG9jY3VycmVuY2UgPT0gIjEiKQ0KbnJvdyhwcmVzZW5jZWR1cCkNCmBgYA0KDQoNCnRoZSBkYXRhIGlzIGluIHByZXNlbmNlZHVwJHRvdGFsX2NlbGxfb2JzX3h5enQNCmBgYHtyIHVuaXF1ZV9wb2ludHBlcmNlbGx9DQp1bmlxdWVfcG9pbnRwZXJjZWxsIDwtIHVuaXF1ZShwcmVzZW5jZWR1cCR0b3RhbF9jZWxsX29ic194eXp0KQ0KdW5pcXVlX3BvaW50cGVyY2VsbA0KYGBgDQpidWdnZXIuLi4gb2sgc28gbGV0cyBkbyBhIGZyZXF1ZW5jeSB0YWJsZQ0KYGBge3IgdW5pcXVlX3BvaW50cGVyY2VsbCBmcmVxdWVuY2llc30NCnBvaW50cGVyY2VsbGNvdW50IDwtIGNvdW50KGNlbG9ic21vcmUxLCAidG90YWxfY2VsbF9vYnNfeHl6dCIpDQpwb2ludHBlcmNlbGxjb3VudCRub19jZWxscyA8LSBwb2ludHBlcmNlbGxjb3VudCRmcmVxIC8gcG9pbnRwZXJjZWxsY291bnQkdG90YWxfY2VsbF9vYnNfeHl6dA0Kd3JpdGUuY3N2KHBvaW50cGVyY2VsbGNvdW50LCBmaWxlID0gIi4uL291dHB1dC9iaW8vcG9pbnRwZXJjZWxsY291bnQuY3N2IikNCnBvaW50cGVyY2VsbGNvdW50DQpgYGANCg0Kc28gdGhlcmUgYXJlIDk0OSAzZCB0aW1lc2xpY2VkIGNlbGxzIHRoYXQgY29udGFpbiBtb3JlIHRoYW4gb25lIG9jY3VycmVuY2UsIGFuZCAyMDQyIHJvd3MuIA0KLSBkaWZmZXJlbnQgc2FtcGxpbmcgZGF5cw0KLSBkaWZmZXJlbnQgY29vcmRpbmF0ZXMNCi0gcmlzayBvZiBkdXBsaWNhdGUgZW50cmllcyAoYnV0IG9ubHkgaWYgdHdvIGluc3RpdHVpb25zIGlucHV0dGVkIHRoZSBzYW1lIGRhdGEgd2l0aCBzbGlnaHRseSBkaWZmZXJlbnQgY29vcmRpbmF0ZXMgYW5kIGRpZmZlcmVudCByZXNlcmNoIHByb2dyYW0gbmFtZXMgLSBzZWUgY2VsbDM5ODVfMThfMjAwMF83IGJlbG93IGFzIGV4YW1wbGUpDQoNCmBgYHtyfQ0KY2VsbDM5ODVfMThfMjAwMF83ICA8LSBzdWJzZXQoY2Vsb2JzbW9yZTEsIGNlbGxfaWRfeHl6dCA9PSAiMzk4NV8xOF8yMDAwXzciKQ0KY2VsbDM5ODVfMThfMjAwMF83IA0KYGBgDQoNCklkZWFsbHkgeW91IG9ubHkgd2FudCBvbmUgb2JzZXJ2YXRpb24gY2VsbCBjZWxsX2lkX3h5enQuIEZpcnN0IHNlZSBpZiBhbnkgYXJlIG1pc3NpbmcgZGVwdGggZGF0YQ0KDQpmaW5kIHRoZSBjb2x1bW4gbnVtYmVycyB0aGF0IGNvcnJlc3BvbmQgdG8gdGhlIGVudi4gZGF0YSAodXNlIGZhc3RtYXRjaCBwYWNrYWdlIGFzIGlzIHF1aWNrZXIpDQoNCmBgYHtyfQ0KZm1hdGNoKCJjaGxfc3VyZmFjZSIsIG5hbWVzKGNlbG9ic21vcmUxKSkgIzI4DQpmbWF0Y2goImNobF9kZXB0aCIsIG5hbWVzKGNlbG9ic21vcmUxKSkgIzI5DQpmbWF0Y2goIm1scF9zdXJmYWNlIiwgbmFtZXMoY2Vsb2JzbW9yZTEpKSAjMzANCmZtYXRjaCgibzJfc3VyZmFjZSIsIG5hbWVzKGNlbG9ic21vcmUxKSkgIzMxDQpmbWF0Y2goIm8yX2RlcHRoIiwgbmFtZXMoY2Vsb2JzbW9yZTEpKSAjMzINCmZtYXRjaCgic2FsaW5pdHlfc3VyZmFjZSIsIG5hbWVzKGNlbG9ic21vcmUxKSkgIzMzDQpmbWF0Y2goInNhbGluaXR5X2RlcHRoIiwgbmFtZXMoY2Vsb2JzbW9yZTEpKSAjMzQNCmZtYXRjaCgic3NoX3N1cmZhY2UiLCBuYW1lcyhjZWxvYnNtb3JlMSkpICMzNQ0KZm1hdGNoKCJ0ZW1wX3N1cmZhY2UiLCBuYW1lcyhjZWxvYnNtb3JlMSkpICMzNg0KZm1hdGNoKCJ0ZW1wX2RlcHRoIiwgbmFtZXMoY2Vsb2JzbW9yZTEpKSAjMzcNCmBgYA0KDQp0aGVuIHN1YnNldCBhbnkgd2l0aCBOQSB2YWx1ZXMNCg0KYGBge3IgY2Vsb2JzbW9yZTFfbm92YWxzfQ0KY2Vsb2JzbW9yZTFfbm92YWxzIDwtICBjZWxvYnNtb3JlMVshY29tcGxldGUuY2FzZXMoY2Vsb2JzbW9yZTFbMjg6MzddKSwgXSAjMjg6MzcgcmVwcmVzZW50IHRoZSBjb2x1bW5zIHcvIGVudi4gZGF0YQ0KbnJvdyhjZWxvYnNtb3JlMV9ub3ZhbHMpICNqdXN0IHRvIGNoZWNrIGhvdyBtYW55IHRoZXJlIGFyZSAtIDEwOTUgb3V0IG9mIDIwNDINCmBgYA0KDQpvayBhbmQgc3Vic2V0IHdpdGggYWxsIHZhbHVlcw0KDQpgYGB7ciBjZWxvYnNtb3JlMV9hbGx2YWx9DQpjZWxvYnNtb3JlMV9hbGx2YWxzIDwtIGNlbG9ic21vcmUxW2NvbXBsZXRlLmNhc2VzKGNlbG9ic21vcmUxWzI4OjM3XSksIF0gIzI4OjM3IHJlcHJlc2VudCB0aGUgY29sdW1ucyB3LyBlbnYuIGRhdGENCm5yb3coY2Vsb2JzbW9yZTFfYWxsdmFscykgIzk0NyBvdXQgb2YgMjA0Mg0KYGBgDQoNCm9rIHNvIGhvdyBtYW55IHVuaXF1ZSBjZWxscyBkbyB3ZSBoYXZlIHdpdGggY29tcGxldGUgZGF0YS4uLg0KDQpgYGB7cn0NCnBvaW50cGVyY2VsbGNvdW50X2FsbGRhdGEgPC0gY291bnQoY2Vsb2JzbW9yZTFfYWxsdmFscywgInRvdGFsX2NlbGxfb2JzX3h5enQiKQ0KcG9pbnRwZXJjZWxsY291bnRfYWxsZGF0YSRub19jZWxscyA8LSBwb2ludHBlcmNlbGxjb3VudF9hbGxkYXRhJGZyZXEgLyBwb2ludHBlcmNlbGxjb3VudF9hbGxkYXRhJHRvdGFsX2NlbGxfb2JzX3h5enQNCndyaXRlLmNzdihwb2ludHBlcmNlbGxjb3VudF9hbGxkYXRhLCBmaWxlID0gIi4uL291dHB1dC9iaW8vcG9pbnRwZXJjZWxsY291bnRfYWxsZGF0YS5jc3YiKQ0KcG9pbnRwZXJjZWxsY291bnRfYWxsZGF0YQ0KYGBgDQoNCmFuZCBzZWUgd2hpY2ggY2VsbF9pZF94eXp0IGFwcGVhciBpbiBib3RoIGNlbG9ic21vcmUxX2FsbHZhbHMgYW5kIGNlbG9ic21vcmUxX25vdmFscw0KYGBge3J9DQpjZWxvYnNtb3JlMV9hbGxub3ZhbHMgPC0gaW5uZXJfam9pbihjZWxvYnNtb3JlMV9hbGx2YWxzLCBjZWxvYnNtb3JlMV9ub3ZhbHMpDQpjZWxvYnNtb3JlMV9hbGxub3ZhbHMgDQpgYGANCk5vbmUuLi4uIHdoaWNoIGlzIGdvb2QuIEknZCBleHBlY3Qgb2JzZXJ2YXRpb25zIGluIHRoZSBzYW1lIHh5enQgdG8gaGF2ZSB0aGUgc2FtZSB2YWx1ZXMNCg0Kc28sIEkgY2FuIHN1Y2Nlc3NmdWxseSByZWR1Y2UgdGhlIG9ic2VydmF0aW9ucyBkb3duIHRvIG9uZSBwZXIgeHl6dA0KDQpgYGB7cn0NCmZtYXRjaCgiY2VsbF9pZF94eXp0IiwgbmFtZXMoY2Vsb2JzbW9yZTEpKSAjNDYNCmR1cGxpY2F0ZXNiZWdvbmUgPC0gY2Vsb2JzbW9yZTFbIWR1cGxpY2F0ZWQoY2Vsb2JzbW9yZTFbICw0Nl0pLCBdICNjcmVhdGVzIGEgZGYgd2l0aCBhbGwgZHVwbGljYXRlcyBnb25lIChub3cgMSBvYnMgcGVyIGNlbGwpDQpucm93KGR1cGxpY2F0ZXNiZWdvbmUpICM5NDkgLSBnb29kDQpwcmVzYWJub2R1cCA8LSBzdWJzZXQocHJlc2FiLCB0b3RhbF9jZWxsX29ic194eXp0ID09ICIxIikgI3JlbW92ZSBhbGwgcm93cyB0aGF0IGhhdmUgbW9yZSB0aGFuIG9uZSBvYnMNCm5yb3cocHJlc2Fibm9kdXApICMxNTQ5MzUxIC0gdGhpcyBhZGRzIHVwIA0KcHJlc2FiIDwtIHJiaW5kKHByZXNhYm5vZHVwLCBkdXBsaWNhdGVzYmVnb25lKQ0KbnJvdyhwcmVzYWIpICMxNTUwMzAwIC0gZ3JlYXQhDQoNCiNyZWNhbGN1bGF0ZSB0aGUgdG90YWxfY2VsbF9vYnNfeHl6dCBjb2x1bW4NCg0KbmFtZXMocHJlc2FiKVtuYW1lcyhwcmVzYWIpPT0idG90YWxfY2VsbF9vYnNfeHl6dCJdIDwtICJYWHRvdGFsX2NlbGxfb2JzX3h5enQiICNyZW5hbWUgY29sDQpvYnNfY2VsbF95eW1tX2RlcHRoX2R1cCA8LSBjb3VudChwcmVzYWIsIGNlbGxfaWQsIHllYXIsIG1vbnRoLCBkZXB0aGxheWVybm8pDQp0ZXN0IDwtIG1lcmdlKHByZXNhYiwgb2JzX2NlbGxfeXltbV9kZXB0aF9kdXAsIGJ5Lng9YygiY2VsbF9pZCIsICJ5ZWFyIiwgIm1vbnRoIiwgImRlcHRobGF5ZXJubyIpLCBieS55PWMoImNlbGxfaWQiLCAieWVhciIsICJtb250aCIsICJkZXB0aGxheWVybm8iKSkNCm5hbWVzKHRlc3QpW25hbWVzKHRlc3QpPT0ibiJdIDwtICJ0b3RhbF9jZWxsX29ic194eXp0IiAjcmVuYW1lIGNvbA0KDQp3cml0ZS5jc3YocHJlc2FiLCAiLi4vb3V0cHV0L2Jpby9wcmVzYWJfY2VsbGlkX3h5enRfbm9kdXAuY3N2IikNCnJtKHByZXNhYm5vZHVwLCBkdXBsaWNhdGVzYmVnb25lLCBjZWxvYnNtb3JlMSwgY2Vsb2JzbW9yZTFfbm92YWxzLCBjZWxvYnNtb3JlMV9hbGxub3ZhbHMsIGNlbG9ic21vcmUxX2FsbHZhbHMpICNqdXN0IGJlY2F1c2UgdGhleSBhcmUgYmlnaXNoIHZhcmlhYmxlcw0KYGBgDQoNCg0KDQojIG1vbnRobHkgc3BlYXJtYW5zIGNvcnJlbGF0aW9ucyBhbmQgVklGDQoNCmN1cmlvdXMgLSBkb2VzIGNvcnJlbGF0aW9ucy92aWYgYWx0ZXIgYmV0d2VlbiBtb250aHM/DQoNCkZpcnN0IHNwbGl0IHRoZSBkYXRhc2V0IGludG8gbW9udGhseQ0KDQpgYGB7ciBzdWJzZXQgbW9udGhseSBwcmVzYWJ9DQpqYW5wcmVzYWIgPC0gc3Vic2V0KHByZXNhYiwgbW9udGggPT0gIjEiKQ0KZmVicHJlc2FiIDwtIHN1YnNldChwcmVzYWIsIG1vbnRoID09ICIyIikNCm1hcnByZXNhYiA8LSBzdWJzZXQocHJlc2FiLCBtb250aCA9PSAiMyIpDQphcHJwcmVzYWIgPC0gc3Vic2V0KHByZXNhYiwgbW9udGggPT0gIjQiKQ0KbWF5cHJlc2FiIDwtIHN1YnNldChwcmVzYWIsIG1vbnRoID09ICI1IikNCmp1bnByZXNhYiA8LSBzdWJzZXQocHJlc2FiLCBtb250aCA9PSAiNiIpDQpqdWxwcmVzYWIgPC0gc3Vic2V0KHByZXNhYiwgbW9udGggPT0gIjciKQ0KYXVncHJlc2FiIDwtIHN1YnNldChwcmVzYWIsIG1vbnRoID09ICI4IikNCnNlcHByZXNhYiA8LSBzdWJzZXQocHJlc2FiLCBtb250aCA9PSAiOSIpDQpvY3RwcmVzYWIgPC0gc3Vic2V0KHByZXNhYiwgbW9udGggPT0gIjEwIikNCm5vdnByZXNhYiA8LSBzdWJzZXQocHJlc2FiLCBtb250aCA9PSAiMTEiKQ0KZGVjcHJlc2FiIDwtIHN1YnNldChwcmVzYWIsIG1vbnRoID09ICIxMiIpDQpgYGANCg0Kbm93IGdldCB0aGUgYmFja2dyb3VuZCBwb2ludHMgZm9yIGVhY2ggbW9udGggKGZvciBzcGVhcm1hbnMpDQpgYGB7ciBtb250aGx5IGJhY2tncm91bmQgcG9pbnRzfQ0KamFuYmFjayA8LSBzdWJzZXQoamFucHJlc2FiLCBvY2N1cnJlbmNlID09ICIwIikNCmZlYmJhY2sgPC0gc3Vic2V0KGZlYnByZXNhYiwgb2NjdXJyZW5jZSA9PSAiMCIpDQptYXJiYWNrIDwtIHN1YnNldChtYXJwcmVzYWIsIG9jY3VycmVuY2UgPT0gIjAiKQ0KYXByYmFjayA8LSBzdWJzZXQoYXBycHJlc2FiLCBvY2N1cnJlbmNlID09ICIwIikNCm1heWJhY2sgPC0gc3Vic2V0KG1heXByZXNhYiwgb2NjdXJyZW5jZSA9PSAiMCIpDQpqdW5iYWNrIDwtIHN1YnNldChqdW5wcmVzYWIsIG9jY3VycmVuY2UgPT0gIjAiKQ0KanVsYmFjayA8LSBzdWJzZXQoanVscHJlc2FiLCBvY2N1cnJlbmNlID09ICIwIikNCmF1Z2JhY2sgPC0gc3Vic2V0KGF1Z3ByZXNhYiwgb2NjdXJyZW5jZSA9PSAiMCIpDQpzZXBiYWNrIDwtIHN1YnNldChzZXBwcmVzYWIsIG9jY3VycmVuY2UgPT0gIjAiKQ0Kb2N0YmFjayA8LSBzdWJzZXQob2N0cHJlc2FiLCBvY2N1cnJlbmNlID09ICIwIikNCm5vdmJhY2sgPC0gc3Vic2V0KG5vdnByZXNhYiwgb2NjdXJyZW5jZSA9PSAiMCIpDQpkZWNiYWNrIDwtIHN1YnNldChkZWNwcmVzYWIsIG9jY3VycmVuY2UgPT0gIjAiKQ0KYGBgDQoNCnJ1biB0aGUgY29ycmVsYXRpb25zIG9uIGVhY2ggbW9udGgncyBiYWNrZ3JvdW5kIHBvaW50cw0KDQpgYGB7ciBtb250aGx5IHNwZWFybWFuIGNvcnJlbGF0aW9uc30NCmphbmJhY2sgPC0gc3Vic2V0KGphbmJhY2ssIHNlbGVjdCA9IGMoYW1vX3NhbXBsZSwgYW1vX3dpbnRlciwgYW1vX3ByZXYsIG5hb19zYW1wbGUsIG5hb193aW50ZXIsIG5hb19wcmV2LCBjaGxfc3VyZmFjZSwgY2hsX2RlcHRoLCBtbHBfc3VyZmFjZSwgc3NoX3N1cmZhY2UsIHRlbXBfc3VyZmFjZSwgdGVtcF9kZXB0aCwgbzJfc3VyZmFjZSwgbzJfZGVwdGgsIHNhbGluaXR5X3N1cmZhY2UsIHNhbGluaXR5X2RlcHRoKSkNCmphbmJhY2tfY29yIDwtIGNvcihqYW5iYWNrLCB1c2U9ImNvbXBsZXRlLm9icyIsIG1ldGhvZCA9ICJzcGVhcm1hbiIpICNuZWVkIHRvIGNyZWF0ZSBhIGNvcnJlbGF0aW9uIHVzaW5nIGNvciB0byBwbG90LiBjb21wbGV0ZS5vYnMgbWVhbnMgbmEucm0gaW4gdGhpcyBwYWNrYWdlLiAjdXNpbmcgc3BlYXJtYW5zIGFzIHN1aXRhYmxlIGZvciBub24tbGluZWFyIHJlbGF0aW9uc2hpcHMNCndyaXRlLmNzdihqYW5iYWNrX2NvciwgIi4uL291dHB1dC9lbnYvamFuYmFja19jb3IuY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkNCg0KZmViYmFjayA8LSBzdWJzZXQoZmViYmFjaywgc2VsZWN0ID0gYyhhbW9fc2FtcGxlLCBhbW9fd2ludGVyLCBhbW9fcHJldiwgbmFvX3NhbXBsZSwgbmFvX3dpbnRlciwgbmFvX3ByZXYsIGNobF9zdXJmYWNlLCBjaGxfZGVwdGgsIG1scF9zdXJmYWNlLCBzc2hfc3VyZmFjZSwgdGVtcF9zdXJmYWNlLCB0ZW1wX2RlcHRoLCBvMl9zdXJmYWNlLCBvMl9kZXB0aCwgc2FsaW5pdHlfc3VyZmFjZSwgc2FsaW5pdHlfZGVwdGgpKQ0KZmViYmFja19jb3IgPC0gY29yKGZlYmJhY2ssIHVzZT0iY29tcGxldGUub2JzIiwgbWV0aG9kID0gInNwZWFybWFuIikgI25lZWQgdG8gY3JlYXRlIGEgY29ycmVsYXRpb24gdXNpbmcgY29yIHRvIHBsb3QuIGNvbXBsZXRlLm9icyBtZWFucyBuYS5ybSBpbiB0aGlzIHBhY2thZ2UuICN1c2luZyBzcGVhcm1hbnMgYXMgc3VpdGFibGUgZm9yIG5vbi1saW5lYXIgcmVsYXRpb25zaGlwcw0Kd3JpdGUuY3N2KGZlYmJhY2tfY29yLCAiLi4vb3V0cHV0L2Vudi9mZWJiYWNrX2Nvci5jc3YiLCByb3cubmFtZXMgPSBUUlVFKQ0KDQptYXJiYWNrIDwtIHN1YnNldChtYXJiYWNrLCBzZWxlY3QgPSBjKGFtb19zYW1wbGUsIGFtb193aW50ZXIsIGFtb19wcmV2LCBuYW9fc2FtcGxlLCBuYW9fd2ludGVyLCBuYW9fcHJldiwgY2hsX3N1cmZhY2UsIGNobF9kZXB0aCwgbWxwX3N1cmZhY2UsIHNzaF9zdXJmYWNlLCB0ZW1wX3N1cmZhY2UsIHRlbXBfZGVwdGgsIG8yX3N1cmZhY2UsIG8yX2RlcHRoLCBzYWxpbml0eV9zdXJmYWNlLCBzYWxpbml0eV9kZXB0aCkpDQptYXJiYWNrX2NvciA8LSBjb3IobWFyYmFjaywgdXNlPSJjb21wbGV0ZS5vYnMiLCBtZXRob2QgPSAic3BlYXJtYW4iKSAjbmVlZCB0byBjcmVhdGUgYSBjb3JyZWxhdGlvbiB1c2luZyBjb3IgdG8gcGxvdC4gY29tcGxldGUub2JzIG1lYW5zIG5hLnJtIGluIHRoaXMgcGFja2FnZS4gI3VzaW5nIHNwZWFybWFucyBhcyBzdWl0YWJsZSBmb3Igbm9uLWxpbmVhciByZWxhdGlvbnNoaXBzDQp3cml0ZS5jc3YobWFyYmFja19jb3IsICIuLi9vdXRwdXQvZW52L21hcmJhY2tfY29yLmNzdiIsIHJvdy5uYW1lcyA9IFRSVUUpDQoNCmFwcmJhY2sgPC0gc3Vic2V0KGFwcmJhY2ssIHNlbGVjdCA9IGMoYW1vX3NhbXBsZSwgYW1vX3dpbnRlciwgYW1vX3ByZXYsIG5hb19zYW1wbGUsIG5hb193aW50ZXIsIG5hb19wcmV2LCBjaGxfc3VyZmFjZSwgY2hsX2RlcHRoLCBtbHBfc3VyZmFjZSwgc3NoX3N1cmZhY2UsIHRlbXBfc3VyZmFjZSwgdGVtcF9kZXB0aCwgbzJfc3VyZmFjZSwgbzJfZGVwdGgsIHNhbGluaXR5X3N1cmZhY2UsIHNhbGluaXR5X2RlcHRoKSkNCmFwcmJhY2tfY29yIDwtIGNvcihhcHJiYWNrLCB1c2U9ImNvbXBsZXRlLm9icyIsIG1ldGhvZCA9ICJzcGVhcm1hbiIpICNuZWVkIHRvIGNyZWF0ZSBhIGNvcnJlbGF0aW9uIHVzaW5nIGNvciB0byBwbG90LiBjb21wbGV0ZS5vYnMgbWVhbnMgbmEucm0gaW4gdGhpcyBwYWNrYWdlLiAjdXNpbmcgc3BlYXJtYW5zIGFzIHN1aXRhYmxlIGZvciBub24tbGluZWFyIHJlbGF0aW9uc2hpcHMNCndyaXRlLmNzdihhcHJiYWNrX2NvciwgIi4uL291dHB1dC9lbnYvYXByYmFja19jb3IuY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkNCg0KbWF5YmFjayA8LSBzdWJzZXQobWF5YmFjaywgc2VsZWN0ID0gYyhhbW9fc2FtcGxlLCBhbW9fd2ludGVyLCBhbW9fcHJldiwgbmFvX3NhbXBsZSwgbmFvX3dpbnRlciwgbmFvX3ByZXYsIGNobF9zdXJmYWNlLCBjaGxfZGVwdGgsIG1scF9zdXJmYWNlLCBzc2hfc3VyZmFjZSwgdGVtcF9zdXJmYWNlLCB0ZW1wX2RlcHRoLCBvMl9zdXJmYWNlLCBvMl9kZXB0aCwgc2FsaW5pdHlfc3VyZmFjZSwgc2FsaW5pdHlfZGVwdGgpKQ0KbWF5YmFja19jb3IgPC0gY29yKG1heWJhY2ssIHVzZT0iY29tcGxldGUub2JzIiwgbWV0aG9kID0gInNwZWFybWFuIikgI25lZWQgdG8gY3JlYXRlIGEgY29ycmVsYXRpb24gdXNpbmcgY29yIHRvIHBsb3QuIGNvbXBsZXRlLm9icyBtZWFucyBuYS5ybSBpbiB0aGlzIHBhY2thZ2UuICN1c2luZyBzcGVhcm1hbnMgYXMgc3VpdGFibGUgZm9yIG5vbi1saW5lYXIgcmVsYXRpb25zaGlwcw0Kd3JpdGUuY3N2KG1heWJhY2tfY29yLCAiLi4vb3V0cHV0L2Vudi9tYXliYWNrX2Nvci5jc3YiLCByb3cubmFtZXMgPSBUUlVFKQ0KDQpqdW5iYWNrIDwtIHN1YnNldChqdW5iYWNrLCBzZWxlY3QgPSBjKGFtb19zYW1wbGUsIGFtb193aW50ZXIsIGFtb19wcmV2LCBuYW9fc2FtcGxlLCBuYW9fd2ludGVyLCBuYW9fcHJldiwgY2hsX3N1cmZhY2UsIGNobF9kZXB0aCwgbWxwX3N1cmZhY2UsIHNzaF9zdXJmYWNlLCB0ZW1wX3N1cmZhY2UsIHRlbXBfZGVwdGgsIG8yX3N1cmZhY2UsIG8yX2RlcHRoLCBzYWxpbml0eV9zdXJmYWNlLCBzYWxpbml0eV9kZXB0aCkpDQpqdW5iYWNrX2NvciA8LSBjb3IoanVuYmFjaywgdXNlPSJjb21wbGV0ZS5vYnMiLCBtZXRob2QgPSAic3BlYXJtYW4iKSAjbmVlZCB0byBjcmVhdGUgYSBjb3JyZWxhdGlvbiB1c2luZyBjb3IgdG8gcGxvdC4gY29tcGxldGUub2JzIG1lYW5zIG5hLnJtIGluIHRoaXMgcGFja2FnZS4gI3VzaW5nIHNwZWFybWFucyBhcyBzdWl0YWJsZSBmb3Igbm9uLWxpbmVhciByZWxhdGlvbnNoaXBzDQp3cml0ZS5jc3YoanVuYmFja19jb3IsICIuLi9vdXRwdXQvZW52L2p1bmJhY2tfY29yLmNzdiIsIHJvdy5uYW1lcyA9IFRSVUUpDQoNCmp1bGJhY2sgPC0gc3Vic2V0KGp1bGJhY2ssIHNlbGVjdCA9IGMoYW1vX3NhbXBsZSwgYW1vX3dpbnRlciwgYW1vX3ByZXYsIG5hb19zYW1wbGUsIG5hb193aW50ZXIsIG5hb19wcmV2LCBjaGxfc3VyZmFjZSwgY2hsX2RlcHRoLCBtbHBfc3VyZmFjZSwgc3NoX3N1cmZhY2UsIHRlbXBfc3VyZmFjZSwgdGVtcF9kZXB0aCwgbzJfc3VyZmFjZSwgbzJfZGVwdGgsIHNhbGluaXR5X3N1cmZhY2UsIHNhbGluaXR5X2RlcHRoKSkNCmp1bGJhY2tfY29yIDwtIGNvcihqdWxiYWNrLCB1c2U9ImNvbXBsZXRlLm9icyIsIG1ldGhvZCA9ICJzcGVhcm1hbiIpICNuZWVkIHRvIGNyZWF0ZSBhIGNvcnJlbGF0aW9uIHVzaW5nIGNvciB0byBwbG90LiBjb21wbGV0ZS5vYnMgbWVhbnMgbmEucm0gaW4gdGhpcyBwYWNrYWdlLiAjdXNpbmcgc3BlYXJtYW5zIGFzIHN1aXRhYmxlIGZvciBub24tbGluZWFyIHJlbGF0aW9uc2hpcHMNCndyaXRlLmNzdihqdWxiYWNrX2NvciwgIi4uL291dHB1dC9lbnYvanVsYmFja19jb3IuY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkNCg0KYXVnYmFjayA8LSBzdWJzZXQoYXVnYmFjaywgc2VsZWN0ID0gYyhhbW9fc2FtcGxlLCBhbW9fd2ludGVyLCBhbW9fcHJldiwgbmFvX3NhbXBsZSwgbmFvX3dpbnRlciwgbmFvX3ByZXYsIGNobF9zdXJmYWNlLCBjaGxfZGVwdGgsIG1scF9zdXJmYWNlLCBzc2hfc3VyZmFjZSwgdGVtcF9zdXJmYWNlLCB0ZW1wX2RlcHRoLCBvMl9zdXJmYWNlLCBvMl9kZXB0aCwgc2FsaW5pdHlfc3VyZmFjZSwgc2FsaW5pdHlfZGVwdGgpKQ0KYXVnYmFja19jb3IgPC0gY29yKGF1Z2JhY2ssIHVzZT0iY29tcGxldGUub2JzIiwgbWV0aG9kID0gInNwZWFybWFuIikgI25lZWQgdG8gY3JlYXRlIGEgY29ycmVsYXRpb24gdXNpbmcgY29yIHRvIHBsb3QuIGNvbXBsZXRlLm9icyBtZWFucyBuYS5ybSBpbiB0aGlzIHBhY2thZ2UuICN1c2luZyBzcGVhcm1hbnMgYXMgc3VpdGFibGUgZm9yIG5vbi1saW5lYXIgcmVsYXRpb25zaGlwcw0Kd3JpdGUuY3N2KGF1Z2JhY2tfY29yLCAiLi4vb3V0cHV0L2Vudi9hdWdiYWNrX2Nvci5jc3YiLCByb3cubmFtZXMgPSBUUlVFKQ0KDQpzZXBiYWNrIDwtIHN1YnNldChzZXBiYWNrLCBzZWxlY3QgPSBjKGFtb19zYW1wbGUsIGFtb193aW50ZXIsIGFtb19wcmV2LCBuYW9fc2FtcGxlLCBuYW9fd2ludGVyLCBuYW9fcHJldiwgY2hsX3N1cmZhY2UsIGNobF9kZXB0aCwgbWxwX3N1cmZhY2UsIHNzaF9zdXJmYWNlLCB0ZW1wX3N1cmZhY2UsIHRlbXBfZGVwdGgsIG8yX3N1cmZhY2UsIG8yX2RlcHRoLCBzYWxpbml0eV9zdXJmYWNlLCBzYWxpbml0eV9kZXB0aCkpDQpzZXBiYWNrX2NvciA8LSBjb3Ioc2VwYmFjaywgdXNlPSJjb21wbGV0ZS5vYnMiLCBtZXRob2QgPSAic3BlYXJtYW4iKSAjbmVlZCB0byBjcmVhdGUgYSBjb3JyZWxhdGlvbiB1c2luZyBjb3IgdG8gcGxvdC4gY29tcGxldGUub2JzIG1lYW5zIG5hLnJtIGluIHRoaXMgcGFja2FnZS4gI3VzaW5nIHNwZWFybWFucyBhcyBzdWl0YWJsZSBmb3Igbm9uLWxpbmVhciByZWxhdGlvbnNoaXBzDQp3cml0ZS5jc3Yoc2VwYmFja19jb3IsICIuLi9vdXRwdXQvZW52L3NlcGJhY2tfY29yLmNzdiIsIHJvdy5uYW1lcyA9IFRSVUUpDQoNCm9jdGJhY2sgPC0gc3Vic2V0KG9jdGJhY2ssIHNlbGVjdCA9IGMoYW1vX3NhbXBsZSwgYW1vX3dpbnRlciwgYW1vX3ByZXYsIG5hb19zYW1wbGUsIG5hb193aW50ZXIsIG5hb19wcmV2LCBjaGxfc3VyZmFjZSwgY2hsX2RlcHRoLCBtbHBfc3VyZmFjZSwgc3NoX3N1cmZhY2UsIHRlbXBfc3VyZmFjZSwgdGVtcF9kZXB0aCwgbzJfc3VyZmFjZSwgbzJfZGVwdGgsIHNhbGluaXR5X3N1cmZhY2UsIHNhbGluaXR5X2RlcHRoKSkNCm9jdGJhY2tfY29yIDwtIGNvcihvY3RiYWNrLCB1c2U9ImNvbXBsZXRlLm9icyIsIG1ldGhvZCA9ICJzcGVhcm1hbiIpICNuZWVkIHRvIGNyZWF0ZSBhIGNvcnJlbGF0aW9uIHVzaW5nIGNvciB0byBwbG90LiBjb21wbGV0ZS5vYnMgbWVhbnMgbmEucm0gaW4gdGhpcyBwYWNrYWdlLiAjdXNpbmcgc3BlYXJtYW5zIGFzIHN1aXRhYmxlIGZvciBub24tbGluZWFyIHJlbGF0aW9uc2hpcHMNCndyaXRlLmNzdihvY3RiYWNrX2NvciwgIi4uL291dHB1dC9lbnYvb2N0YmFja19jb3IuY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkNCg0Kbm92YmFjayA8LSBzdWJzZXQobm92YmFjaywgc2VsZWN0ID0gYyhhbW9fc2FtcGxlLCBhbW9fd2ludGVyLCBhbW9fcHJldiwgbmFvX3NhbXBsZSwgbmFvX3dpbnRlciwgbmFvX3ByZXYsIGNobF9zdXJmYWNlLCBjaGxfZGVwdGgsIG1scF9zdXJmYWNlLCBzc2hfc3VyZmFjZSwgdGVtcF9zdXJmYWNlLCB0ZW1wX2RlcHRoLCBvMl9zdXJmYWNlLCBvMl9kZXB0aCwgc2FsaW5pdHlfc3VyZmFjZSwgc2FsaW5pdHlfZGVwdGgpKQ0Kbm92YmFja19jb3IgPC0gY29yKG5vdmJhY2ssIHVzZT0iY29tcGxldGUub2JzIiwgbWV0aG9kID0gInNwZWFybWFuIikgI25lZWQgdG8gY3JlYXRlIGEgY29ycmVsYXRpb24gdXNpbmcgY29yIHRvIHBsb3QuIGNvbXBsZXRlLm9icyBtZWFucyBuYS5ybSBpbiB0aGlzIHBhY2thZ2UuICN1c2luZyBzcGVhcm1hbnMgYXMgc3VpdGFibGUgZm9yIG5vbi1saW5lYXIgcmVsYXRpb25zaGlwcw0Kd3JpdGUuY3N2KG5vdmJhY2tfY29yLCAiLi4vb3V0cHV0L2Vudi9ub3ZiYWNrX2Nvci5jc3YiLCByb3cubmFtZXMgPSBUUlVFKQ0KDQpkZWNiYWNrIDwtIHN1YnNldChkZWNiYWNrLCBzZWxlY3QgPSBjKGFtb19zYW1wbGUsIGFtb193aW50ZXIsIGFtb19wcmV2LCBuYW9fc2FtcGxlLCBuYW9fd2ludGVyLCBuYW9fcHJldiwgY2hsX3N1cmZhY2UsIGNobF9kZXB0aCwgbWxwX3N1cmZhY2UsIHNzaF9zdXJmYWNlLCB0ZW1wX3N1cmZhY2UsIHRlbXBfZGVwdGgsIG8yX3N1cmZhY2UsIG8yX2RlcHRoLCBzYWxpbml0eV9zdXJmYWNlLCBzYWxpbml0eV9kZXB0aCkpDQpkZWNiYWNrX2NvciA8LSBjb3IoZGVjYmFjaywgdXNlPSJjb21wbGV0ZS5vYnMiLCBtZXRob2QgPSAic3BlYXJtYW4iKSAjbmVlZCB0byBjcmVhdGUgYSBjb3JyZWxhdGlvbiB1c2luZyBjb3IgdG8gcGxvdC4gY29tcGxldGUub2JzIG1lYW5zIG5hLnJtIGluIHRoaXMgcGFja2FnZS4gI3VzaW5nIHNwZWFybWFucyBhcyBzdWl0YWJsZSBmb3Igbm9uLWxpbmVhciByZWxhdGlvbnNoaXBzDQp3cml0ZS5jc3YoZGVjYmFja19jb3IsICIuLi9vdXRwdXQvZW52L2RlY2JhY2tfY29yLmNzdiIsIHJvdy5uYW1lcyA9IFRSVUUpDQpgYGANCg0KDQoNCiNtYXhlbnQ/DQoNCmBgYHtyfQ0KbGlicmFyeSgicmFzdGVyIikNCmxpYnJhcnkoImRpc21vIikNCmxpYnJhcnkoInJnZW9zIikNCmBgYA0KDQo=